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

时间:2015-08-03 03:23:57

标签: c# dynamic anonymous-types

我有一个返回匿名类型的函数(为简化说明而简化)...

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

当我这样做时......

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

它输出这个(就像我在直接窗口中做'?pi'一样)......

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

但如果我尝试这样做......

   string propertyName = pi.PropertyName;

...它编译但抛出运行时异常说

  

抛出异常:System.Core.dll中的“Microsoft.CSharp.RuntimeBinder.RuntimeBinderException”

     

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

是什么给出的?我在这里缺少什么?

3 个答案:

答案 0 :(得分:10)

问题在于anonymous types are internal,这意味着您无法使用dynamic属性访问者从其创建的项目以外的项目访问其属性。动态绑定将它们视为它知道的最近的公共继承类型 - object

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

如果您绝对必须在此使用dynamic,则下一个最佳选择可能是更改您的AssemblyInfo.cs文件,以使您可以访问项目的内部属性。重新尝试从以下位置访问它们:

[assembly:InternalsVisibleTo("MyOtherProject")]

答案 1 :(得分:2)

修改

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

旧答案

您需要使用ExpandoObject。参考here

事实上,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")。

答案 2 :(得分:1)

此外,您可以使用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

Fiddle demo