none
Get a variable type using reflection RRS feed

  • Question

  • I am not sure if this is the right forum to ask my question, if not please anyone let me know the better one.

    I am developing an application which allows a user to enter c# code and it is built at runtime.

    I also want to provide the user a simplified intelli-sense like feature. So when the mouse is moved over an identifier in the code text I want to display the details like type, value and parameters if it is a method name.

    Currently I am facing with the following problem : assume the code is error-free and I can compile it. Let's say there is an identifier in the code named Foo.Whatewer.Something. The compiler obviously understands this. How can I get some information about an identifier if I only know its name "Foo.Whatever.Something" ?

    There is well-defined object model in the built runtime code and I have the type and instance of the referring class (the class containing the code with the identifier "Foo.Whatewer.Something" ). Currently I am making assumptions that Foo is a variable in the referring object and I can use reflection this way to get the information I want.

    But this is too specific and does not work if the user code refers to a class outside of my defined object model, for instance to a File class.

    I want to have a more general approach, the way the compiler can resolve the reference.

    What is the correct way ? Any ideas please ?

    Wednesday, December 30, 2015 2:15 PM

Answers

  • I found a solution, which is partly also an answer to my original post:

    foreach (var thisAssembly in AppDomain.CurrentDomain.GetAssemblies())
    {
      type t = thisAssembly.GetType(typeName);
      if (t != null) return t;
    }

    • Marked as answer by Lac Saturday, January 2, 2016 2:38 PM
    Saturday, January 2, 2016 2:38 PM
  • The static method 'Type.GetType(string)' usually requires an assembly qualified name. You can omit the assembly details and use the 'full name' if it's defined in the calling assembly or mscorlib ... but "System.Diagnostics.Debug" is defined in the "System" assembly and so doesn't qualify. "System.String" and "System.Int32" worked because those types are defined in mscorlib which is used as a fallback assembly.

    Try this:

    Type.GetType("System.Diagnostics.Debug, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089");

    The instance method 'Assembly.GetType(string)' only searches for the type in the assembly on which it is called, and 'Assembly.GetExecutingAssembly()' returns the assembly calling the method (the assembly you compiled from this code).

    Try this:

    Assembly.Load("System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089").GetType("System.Diagnostics.Debug");
    Note. looking for the type in any assembly that happens to be already loaded into the current app domain has some issues that you should be aware of:
    • Another assembly might have been loaded that also defines a type with the same name. This can lead to errors (or worse, a security vulnerability).
    • The assembly defining the type might not be loaded yet.
    • Marked as answer by Lac Thursday, January 7, 2016 1:46 PM
    Monday, January 4, 2016 12:54 PM

All replies

  • Hi Lac,

    Based on your description, there are 3 scenarios what I think, you can think out the two easier way.

    1. Some Assembly from System
    2. Some custom dll that your referenced
              //1:System
    
                Type a = Type.GetType("System.Int32");
                Console.WriteLine(a.FullName);
    
                //2: get type from a dll
             
                Assembly ass=Assembly.LoadFrom("XXXX.dll");
                var type = ass.GetType("InstanceName");

    The hardest is as you said, if the user code refers to a class outside. You may need to use  Lexical Analysis. For more details, please check the interesting blog can be found at the following link:

    http://blogs.microsoft.co.il/sasha/2010/10/06/writing-a-compiler-in-c-lexical-analysis/

    And in this[^] question you can find a huge count of links to articles.

    The main point are lexical analyzer and parser, you'll probably use the *nix tools lex and yacc.  And uninterestingly enough, the book called "lex and yacc" picked up where the Dragon Book left off for this part.

    http://luv.asn.au/overheads/lex_yacc/index.html

    Best regards,

    Kristin


    We are trying to better understand customer views on social support experience, so your participation in this interview project would be greatly appreciated if you have time. Thanks for helping make community forums a great place.
    Click HERE to participate the survey.


    • Edited by Kristin Xie Thursday, December 31, 2015 3:25 AM
    Thursday, December 31, 2015 3:22 AM
  • Thanks Kristin for the answer, I will experiment with Type.GetType(), but as far as I remember I did some checks with this without success.

    You referenced System.String, but one of the problem is that I can't always decide what is the correct namespace for an identifier (type or class). 

    Thursday, December 31, 2015 12:07 PM
  • Kristin, 

    as I was coding Type.GetType() as you suggested, I realized it does not work for example to Debug. Although it works for String or Int32 perfectly.

    I mean, the call Type.GetType("System.Diagnostics.Debug") always returns null, even if the code compiles with no errors.I also tried Assembly.GetExecutingAssembly().GetType("System.Diagnostics.Debug") but it also returned null.

    Can you explain me why ?

    Thanks in advance.

    Friday, January 1, 2016 2:40 PM
  • I found a solution, which is partly also an answer to my original post:

    foreach (var thisAssembly in AppDomain.CurrentDomain.GetAssemblies())
    {
      type t = thisAssembly.GetType(typeName);
      if (t != null) return t;
    }

    • Marked as answer by Lac Saturday, January 2, 2016 2:38 PM
    Saturday, January 2, 2016 2:38 PM
  • The static method 'Type.GetType(string)' usually requires an assembly qualified name. You can omit the assembly details and use the 'full name' if it's defined in the calling assembly or mscorlib ... but "System.Diagnostics.Debug" is defined in the "System" assembly and so doesn't qualify. "System.String" and "System.Int32" worked because those types are defined in mscorlib which is used as a fallback assembly.

    Try this:

    Type.GetType("System.Diagnostics.Debug, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089");

    The instance method 'Assembly.GetType(string)' only searches for the type in the assembly on which it is called, and 'Assembly.GetExecutingAssembly()' returns the assembly calling the method (the assembly you compiled from this code).

    Try this:

    Assembly.Load("System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089").GetType("System.Diagnostics.Debug");
    Note. looking for the type in any assembly that happens to be already loaded into the current app domain has some issues that you should be aware of:
    • Another assembly might have been loaded that also defines a type with the same name. This can lead to errors (or worse, a security vulnerability).
    • The assembly defining the type might not be loaded yet.
    • Marked as answer by Lac Thursday, January 7, 2016 1:46 PM
    Monday, January 4, 2016 12:54 PM