简体   繁体   English

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

[英]Why can't I access properties of an anonymous type returned from a function via the dynamic keyword?

I have a function that returns an anonymous type like so (simplified for illustrative purposes)... 我有一个函数返回一个像这样的匿名类型(简化为说明目的)...

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

When I do this... 我这样做的时候......

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

It outputs this (the same as if I did '?pi' in the immediate window)... 它输出这个(就像我在即时窗口中做'?pi'一样)......

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

But if I try doing this... 但如果我尝试这样做......

   string propertyName = pi.PropertyName;

...it compiles but throws a runtime exception saying ...它编译但抛出运行时异常说

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

Additional information: 'object' does not contain a definition for 'PropertyName' 附加信息:'object'不包含'PropertyName'的定义

What gives? 是什么赋予了? What am I missing here? 我在这里错过了什么?

The problem is that anonymous types are internal , which means that you can't access their properties with dynamic property accessors from projects other than the one they were created in. The dynamic binding treats them as the closest public inherited type it knows about-- object . 问题是匿名类型是内部的 ,这意味着您无法使用dynamic属性访问器从其创建的项目以外的项目访问其属性。动态绑定将它们视为它知道的最接近的公共继承类型 - object

To fix this, you can declare a public type to represent the values you're expecting to find in your anonymous type. 要解决此问题,您可以声明一个公共类型来表示您希望在匿名类型中找到的值。 This is probably a good idea anyway, since you're clearly expecting to consume the returned properties in other parts of your code. 无论如何,这可能是一个好主意,因为您显然希望在代码的其他部分使用返回的属性。 Using a declared type also enables you to maintain type-safety, avoiding the need for dynamic entirely. 使用声明的类型还可以使您保持类型安全,从而完全不需要dynamic

If you absolutely must use dynamic s here, the next best option is probably to change your AssemblyInfo.cs file to make internal properties accessible to the project you're trying to access them from: 如果你绝对必须在这里使用dynamic ,那么下一个最佳选择可能是更改你的AssemblyInfo.cs文件,使你试图从中访问它们的项目可以访问内部属性:

[assembly:InternalsVisibleTo("MyOtherProject")]

Edit 编辑

According to your edit. 根据你的编辑。 Apparently you are not required dynamic at all as there are no dynamic properties. 显然你根本不需要动态,因为没有动态属性。 Just create a concrete type with your predefined properties. 只需使用预定义属性创建具体类型即可。 It's better to avoid dynamic when possible anyway. 无论如何,最好避免动态。

Old Answer 老答案

You need to use an ExpandoObject . 您需要使用ExpandoObject Reference here . 参考这里

In fact, GetPropertyInfo() should return an 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;
    }

The ExpandoObject class enables you to add and delete members of its instances at run time and also to set and get values of these members. ExpandoObject类使您可以在运行时添加和删除其实例的成员,还可以设置和获取这些成员的值。 This class supports dynamic binding, which enables you to use standard syntax like sampleObject.sampleMember instead of more complex syntax like sampleObject.GetAttribute("sampleMember"). 此类支持动态绑定,使您可以使用标准语法(如sampleObject.sampleMember)而不是像sampleObject.GetAttribute(“sampleMember”)这样的更复杂的语法。

Also, you can use System.Reflection 此外,您可以使用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 小提琴演示

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM