为什么 C# 动态解析内部属性而不是方法
本文关键字:方法 属性 内部 动态 为什么 | 更新日期: 2023-09-27 18:31:01
我有一个包含以下类的库:
public interface IEntity
{
string Foo { get; }
void Bar(int x);
}
public class EntityFactory
{
public static IEntity createEntity()
{
return new Entity();
}
}
internal class Entity : DynamicObject, IEntity
{
public void Bar(int x)
{
Console.WriteLine("inside Bar");
Console.WriteLine("bar {0}", x);
}
public string Foo
{
get
{
Console.WriteLine("inside Foo getter");
return "foo";
}
}
public override bool TryInvokeMember(InvokeMemberBinder binder, object[] args, out object result)
{
Console.WriteLine("inside TryInvokeMember(binder.Name = '{0}')", binder.Name);
return base.TryInvokeMember(binder, args, out result);
}
public override bool TryGetMember(GetMemberBinder binder, out object result)
{
Console.WriteLine("inside TryGetMember(binder.Name = '{0}')", binder.Name);
if (binder.Name == "SomeVar")
{
result = 42;
return true;
}
return base.TryGetMember(binder, out result);
}
}
以及使用它们的程序:
public static void Main(string[] args)
{
dynamic entity = EntityFactory.createEntity();
Console.WriteLine("entity.Foo = {0}", entity.Foo);
entity.Bar(24);
Console.WriteLine("entity.SomeVar = {0}", entity.SomeVar);
}
输出为
inside Foo getter
entity.Foo = foo
inside TryInvokeMember(binder.Name = 'Bar')
inside TryGetMember(binder.Name = 'Bar')
然后我收到异常
Microsoft.CSharp.RuntimeBinder.RuntimeBinderException: `EntityLib.Entity.Bar(int)' is inaccessible due to its protection level
为什么动态对象直接访问属性Foo
,但无法调用方法 Bar
并改用 TryInvokeMember
和 TryGetMember
?它们具有相同的访问修饰符。
更新:在单声道上观察到所描述的行为。Microsoft在访问Foo
属性时已经失败。以下代码按预期工作:
public static void Main(string[] args)
{
var entity = EntityFactory.createEntity();
entity.Bar(24);
Console.WriteLine("entity.Foo = {0}", entity.Foo);
dynamic e = entity;
Console.WriteLine("entity.SomeVar = {0}", e.SomeVar);
}
这是错误还是功能将由微软决定。但是,我希望将变量转换为动态不应限制访问。
internal class Entity ....
动态关键字不是受限可访问性的解决方法。 Entity 类被声明为内部的,因此尝试从不属于 Entity 所在的程序集的代码调用其 Bar() 方法将被绑定程序拒绝,该消息几乎没有留下任何想象力:
EntityLib.Entity.Bar(int)' 由于其保护级别而无法访问
实现目标的逻辑方法是将实体类声明为公共。 如果由于某种原因这是一个问题,那么您可以使用反射打破规则。 您需要使用 BindingFlags.NonPublic |Type.GetMethod() 调用中的 BindingFlag.Instance 选项。
至于核心问题,我很乐意将其视为错误。 C# DLR 绑定程序无法进行反向工程。 至少不是因为它的代码不包含在参考源中,Microsoft似乎确实将其视为商业秘密。 是的。 您可以在 connect.microsoft.com 提交