我正在尝试按照Pro C#5.0这本书上的例子,我偶然发现了一个我无法工作的例子:
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;
这是CarLibrary的声明:
namespace CarLibrary {
// UPDATE: I just realized that I had declared MiniVan internal
internal MiniVan {
public void TurboBoost() {
Console.WriteLine("Turbo Boosting");
}
}
}
因此,即使MiniVan被声明为INTERNAL,使用Reflection我仍然可以创建一个MiniVan实例,并调用TurboBoost()。但是如果我使用dynamic关键字,则调用TurboBoost()不起作用。如果MiniVan被声明为PUBLIC,则两种情况都可以完美地运行。
有人可以告诉我这是不是所谓的那样?
答案 0 :(得分:3)
dynamic
尊重可访问性规则,其中不仅包括成员的可访问性,还包括对象的类型是internal
,private
(嵌套)等等。dynamic
不是只是围绕反射的包装器 - 它更多:这可以在常规的C#中使用。
这意味着在dynamic
程序集中执行的CarLibrary
的相同使用会起作用。如果您想通过dynamic
访问类型成员,那么它必须是public
,或者至少是:在调用上下文中可访问。
特别是,这可以防止您通过访问从未应该直接了解的public
类型的internal
成员来欺骗运行时。例如,假设核心CLI类型实现了一些接口:
public ISomeInterface {...}
internal SomeMicrosoftType : ISomeInterface
{
public void FireTheMissiles() {...}
}
现在;可能有一个API将该对象公开为ISomeInterface
实例 - 因此我们可以合法地引用该对象。在我们的常规代码中,我们可以访问ISomeInterface
的成员,但我们无法调用FireTheMissiles
。但是,如果您建议工作,那么我们可以这样做:
ISomeInterface innocent = ...
dynamic evil = innocent;
evil.FireTheMissiles();
现在,是我们可以通过 reflection 来做到这一点,但反射有额外的检查,特别是如果我们没有完全信任的话。