匿名types – 是否有任何distingushing特性?

有没有什么可以用来确定一个types是否实际上是一个匿名types? 例如一个接口等?

目标是创build如下的东西…

//defined like... public static T Get<T>(this IAnonymous obj, string prop) { return (T)obj.GetType().GetProperty(prop).GetValue(obj, null); } //... //And then used like... var something = new { name = "John", age = 25 }; int age = something.Get<int>("age"); 

还是仅仅是一个匿名types的美丽? 没有什么可以识别自己,因为它需要一个新的形状?

注意 – 我意识到你可以为对象类写一个扩展方法,但在我看来,这似乎有点矫枉过正。

编辑:下面的列表适用于C#匿名types。 VB.NET有不同的规则 – 特别是,它可以生成可变的匿名types(默认情况下)。 Jared在评论中指出,命名风格也是不同的。 基本上这是非常脆弱的…

您不能在通用约束中识别它,但是:

  • 它将是一个类(而不是接口,枚举,结构等)
  • 它将应用CompilerGeneratedAttribute
  • 它将覆盖Equals,GetHashCode和ToString
  • 它将位于全局命名空间中
  • 它不会嵌套在另一种types中
  • 这将是内部的
  • 它将被密封
  • 它将直接从object派生
  • 它将与属性一样具有许多types参数。 (你可以有一个非generics的匿名types,没有属性,但是有点没有意义。)
  • 每个属性都有一个types参数,其名称包括属性名称,并且将是该types的参数,例如,Name属性成为types<> _ Name的属性
  • 每个属性将是公共和只读
  • 对于每个财产将有一个相应的只读私人领域
  • 将不会有其他的财产或领域
  • 将会有一个构造函数,每个types参数对应一个参数,顺序与types参数相同
  • 每个方法和属性都将应用DebuggerHiddenAttribute 。
  • 该types的名称将以“<>”开头,并包含“AnonymousType”

但是,很less有这样的规格保证 – 所以它可以在下一版本的编译器中改变,或者如果你使用Mono等。

我记得,有一个[CompilerGenerated]标记… 2秒

加上这个名字会很怪,而且会是一个genericstypes; -p

其实,对于“得到”等我可能只是使用静态(非扩展)的方法。

如果你只是想从一个anon-type的实例(在以后的时间点)获取值,lambda可能是最好的select – 注意你需要一些技巧来解决这个问题:

  static void Main() { var foo = new { name = "John", age = 25 }; var func = Get(foo, x => x.age); var bar = new { name = "Marc", age = 30 }; int age = func(bar); } // template here is just for type inference... static Func<TSource, TValue> Get<TSource, TValue>( TSource template, Func<TSource, TValue> lambda) { return lambda; } 

(编辑评论)肯定这个属性:

  var foo = new { A = "B" }; Type type = foo.GetType(); CompilerGeneratedAttribute attrib = (CompilerGeneratedAttribute) Attribute.GetCustomAttribute( type, typeof(CompilerGeneratedAttribute)); // non-null, therefore is compiler-generated 

为了扩展方法的目的,无法区分匿名types。 扩展方法通过指定编译时可命名types的方法来工作。 匿名types是不可命名的,因此在编译时不可见。 这使得它们与扩展方法不兼容。