首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >“C#”“dynamic”不能从另一个程序集中声明的匿名类型访问属性

“C#”“dynamic”不能从另一个程序集中声明的匿名类型访问属性
EN

Stack Overflow用户
提问于 2010-04-13 22:34:01
回答 8查看 39.1K关注 0票数 88

只要我在与Program类相同的程序集中有ClassSameAssembly类,下面的代码就可以很好地工作。但是,当我将类ClassSameAssembly移动到单独的程序集中时,抛出了一个RuntimeBinderException (如下所示)。有可能解决这个问题吗?

代码语言:javascript
复制
using System;

namespace ConsoleApplication2
{
    public static class ClassSameAssembly
    {
        public static dynamic GetValues()
        {
            return new
            {
                Name = "Michael", Age = 20
            };
        }
    }

    internal class Program
    {
        private static void Main(string[] args)
        {
            var d = ClassSameAssembly.GetValues();
            Console.WriteLine("{0} is {1} years old", d.Name, d.Age);
        }
    }
}

Microsoft.CSharp.RuntimeBinder.RuntimeBinderException’不包含‘Name’的定义

代码语言:javascript
复制
at CallSite.Target(Closure , CallSite , Object )
at System.Dynamic.UpdateDelegates.UpdateAndExecute1[T0,TRet](CallSite site, T0 arg0)
at ConsoleApplication2.Program.Main(String[] args) in C:\temp\Projects\ConsoleApplication2\ConsoleApplication2\Program.cs:line 23
EN

回答 8

Stack Overflow用户

回答已采纳

发布于 2010-04-13 22:42:17

我认为问题在于匿名类型是作为internal生成的,因此绑定器并不真正“知道”它本身。

尝试使用ExpandoObject:

代码语言:javascript
复制
public static dynamic GetValues()
{
    dynamic expando = new ExpandoObject();
    expando.Name = "Michael";
    expando.Age = 20;
    return expando;
}

我知道这有点丑陋,但这是目前我能想到的最好的……我认为你甚至不能对它使用对象初始化器,因为尽管它被强类型化为ExpandoObject,但编译器不知道如何处理"Name“和"Age”。您可以执行以下操作:

代码语言:javascript
复制
 dynamic expando = new ExpandoObject()
 {
     { "Name", "Michael" },
     { "Age", 20 }
 };
 return expando;

但这也好不到哪里去。

您可能会编写一个扩展方法,通过反射将匿名类型转换为具有相同内容的扩展。然后你可以这样写:

代码语言:javascript
复制
return new { Name = "Michael", Age = 20 }.ToExpando();

这真是太可怕了:

票数 118
EN

Stack Overflow用户

发布于 2010-08-18 20:24:40

您可以使用[assembly: InternalsVisibleTo("YourAssemblyName")]使您的程序集内部可见。

票数 63
EN

Stack Overflow用户

发布于 2011-01-04 21:18:29

我遇到了一个类似的问题,我想补充说Jon Skeets回答说还有另一个选择。我发现的原因是我意识到Asp MVC3中的许多扩展方法都使用匿名类作为输入来提供html属性(新的{alt="Image alt",style=“padding: 5px"} =>

无论如何,这些函数使用RouteValueDictionary类的构造函数。我自己试过了,它确实有效--尽管只有第一层(我使用的是多层结构)。因此-在代码中,这将是:

代码语言:javascript
复制
object o = new {
    name = "theName",
    props = new {
        p1 = "prop1",
        p2 = "prop2"
    }
}
SeparateAssembly.TextFunc(o)

//In SeparateAssembly:
public void TextFunc(Object o) {
  var rvd = new RouteValueDictionary(o);

//Does not work:
Console.WriteLine(o.name);
Console.WriteLine(o.props.p1);

//DOES work!
Console.WriteLine(rvd["name"]);

//Does not work
Console.WriteLine(rvd["props"].p1);
Console.WriteLine(rvd["props"]["p1"]);

所以..。这到底是怎么回事?在RouteValueDictionary内部可以看到以下代码(上面的值为~= o):

代码语言:javascript
复制
foreach (PropertyDescriptor descriptor in TypeDescriptor.GetProperties(values))
    object obj2 = descriptor.GetValue(values);
    //"this.Add" would of course need to be adapted
    this.Add(descriptor.Name, obj2);
}

所以-使用TypeDescriptor.GetProperties(o)我们将能够获得属性和值,尽管匿名类型在单独的程序集中被构造为内部类型!当然,这很容易扩展,使其成为递归。如果你愿意,还可以做一个扩展方法。

希望这能有所帮助!

/Victor

票数 11
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/2630370

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档