Question

I'm trying to follow the examples on the book Pro C# 5.0, and I've stumbled upon one that I cannot make work:

static void Main() {

    Assembly asm = Assembly.Load("CarLibrary");

    Type MiniVan = asm.GetType("CarLibrary.MiniVan");

    dynamic d = Activator.CreateInstance(Minivan);

    Console.WriteLine("Type of d is {0}", d.GetType()); // Type is CarLibrary.MiniVan

    MethodInfo m = MiniVan.GetMethod("TurboBoost");
    m.Invoke(d, null); // This works fine, and prints out "Turbo Boosting"

    d.TurboBoost(); // This doesn't work like the book says it should. 
                    // I get: object does not contain a definition for TurboBoost;

Here's the declaration of CarLibrary:

namespace CarLibrary {

    // UPDATE: I just realized that I had declared MiniVan internal
    internal MiniVan {

        public void TurboBoost() {

            Console.WriteLine("Turbo Boosting");
        }
    }
}

So, even though MiniVan is declared as INTERNAL, using Reflection I can still create an instance of MiniVan, and make a call to TurboBoost(). But if I use the dynamic keyword, a call to TurboBoost() doesn't work. If MiniVan is declared PUBLIC though, both cases work perfectly.

Could someone tell me if all that is as it's suppose to be?

Was it helpful?

Solution

dynamic respects the accessibility rules, which includes not just the member's accessibility, but also whether the object's type is internal, private (nested), etc. dynamic is not just a wrapper around reflection - it is more: would this have worked in regular C# from here.

Which means that the same use of dynamic executed inside the CarLibrary assembly, would have worked. If you want to access type-members via dynamic, then it must be public, or at a minimum: accessible in the calling context.

In particular, this prevents you from cheating the runtime by accessing public members of internal types that you were never supposed to know about directly. For example, suppose a core CLI type implements some interface:

public ISomeInterface {...}
internal SomeMicrosoftType : ISomeInterface
{
    public void FireTheMissiles() {...}
}

Now; there may well be an API that exposes that object as an ISomeInterface instance - so we could legitimately have a reference to an object of that. In our regular code, we could have accessed members of ISomeInterface, but we would not have been able to call FireTheMissiles. However, if what you are suggesting worked, then we could do:

ISomeInterface innocent = ...
dynamic evil = innocent;
evil.FireTheMissiles();

Now, yes we can do that via reflection, but reflection has additional checks, especially if we aren't running with full trust.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top