为什么我不能通过dynamic关键字访问从函数返回的匿名类型的属性?

本文关键字:返回 类型 属性 函数 不能 dynamic 访问 关键字 为什么 | 更新日期: 2023-09-27 18:06:12

我有一个函数,它返回一个匿名类型,如下所示(为了便于说明而简化)…

public object GetPropertyInfo()
{
    return new {
        PropertyName = "Foo",
        Value = "Laa"
    };
}

当我这样做的时候…

dynamic pi = GetPropertyInfo();
Console.WriteLine(pi);

它输出这个(如果我做'?

{ PropertyName = "A", Value = 44 }
    PropertyName: "A"
    Value: 44

但是如果我尝试这样做…

   string propertyName = pi.PropertyName;

…它编译,但抛出一个运行时异常,说

抛出异常:'Microsoft.CSharp.RuntimeBinder. 'RuntimeBinderException' in System.Core.dll

附加信息:'object'不包含'PropertyName'的定义

给了什么?我遗漏了什么?

为什么我不能通过dynamic关键字访问从函数返回的匿名类型的属性?

问题是匿名类型是内部的,这意味着您不能使用dynamic属性访问器从其他项目访问它们的属性,而不是创建它们的项目。动态绑定将它们视为它所知道的最接近的公共继承类型——object

要解决这个问题,可以声明一个公共类型来表示您希望在匿名类型中找到的值。无论如何,这可能是个好主意,因为您显然希望在代码的其他部分使用返回的属性。使用声明的类型还使您能够维护类型安全,从而完全避免了对dynamic的需要。

如果你绝对必须在这里使用dynamic s,下一个最好的选择可能是改变你的AssemblyInfo.cs文件,使内部属性可以访问到你试图访问它们的项目:

[assembly:InternalsVisibleTo("MyOtherProject")]

编辑

根据你的编辑。显然根本不需要动态,因为没有动态属性。只需用预定义的属性创建一个具体类型。无论如何,最好尽可能避免动态。

老回答

您需要使用ExpandoObject。参考这里。

实际上,GetPropertyInfo()应该返回一个ExpandoObject

    dynamic foo = this.GetPropertyInfo();
    string i = foo.MyPropertyName;
    private ExpandoObject GetPropertyInfo()
    {
        dynamic obj = new ExpandoObject();
        obj.PropertyName = "MyPropertyName";
        obj.PropertyType = "MyPropertyType";
        return obj;
    }

ExpandoObject类允许您添加和删除其实例,以及设置和获取这些成员的值。该类支持动态绑定,这使您能够使用标准语法类似于sampleObject。sampleMember而不是更复杂的语法像sampleObject.GetAttribute("sampleMember")。

也可以使用System.Reflection

object D = GetPropertyInfo(); 
Type t = D.GetType(); // get object's type
PropertyInfo p = t.GetProperty("PropertyName"); // look up for the property:
object P = p.GetValue(D, null); // get the value

小提琴演示