为什么 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 并改用 TryInvokeMemberTryGetMember?它们具有相同的访问修饰符。

更新:在单声道上观察到所描述的行为。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);
}

这是错误还是功能将由微软决定。但是,我希望将变量转换为动态不应限制访问。

为什么 C# 动态解析内部属性而不是方法

 internal class Entity ....

动态关键字不是受限可访问性的解决方法。 Entity 类被声明为内部的,因此尝试从不属于 Entity 所在的程序集的代码调用其 Bar() 方法将被绑定程序拒绝,该消息几乎没有留下任何想象力:

EntityLib.Entity.Bar(int)' 由于其保护级别而无法访问

实现目标的逻辑方法是将实体类声明为公共。 如果由于某种原因这是一个问题,那么您可以使用反射打破规则。 您需要使用 BindingFlags.NonPublic |Type.GetMethod() 调用中的 BindingFlag.Instance 选项。

至于核心问题,我很乐意将其视为错误。 C# DLR 绑定程序无法进行反向工程。 至少不是因为它的代码不包含在参考源中,Microsoft似乎确实将其视为商业秘密。 是的。 您可以在 connect.microsoft.com 提交