2008-11-24 54 views
22

有没有什么可用来确定一个类型是否实际上是一个匿名类型?例如一个接口等?匿名类型 - 是否有任何distingushing特性?

的目标是创建类似下面的...

//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"); 

或者是匿名类型的仅仅是美?没有什么可以自我识别,因为它需要一个新的形状?

注意 - 我知道你可以写为对象类的扩展方法,但似乎有点矫枉过正,在我看来。

回答

48

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

你不能确定它在通用约束,但:

  • 这将是一个类(而不是接口,枚举,结构等)
  • 这将有适用于它的CompilerGeneratedAttribute
  • 将重载Equals,GetHashCode的和toString
  • 这将是在全局命名空间
  • 它不会被嵌套在另一个类型
  • 这将是内部
  • 将密封
  • 它将从object
  • 直接导出这将是通用的与尽可能多的类型的参数作为属性。 (你可以有一个非通用的匿名类型,没有任何属性,但它有点没有意义。)
  • 每个属性将具有与包含属性名的名称的类型参数,并且将是类型参数,例如的名称属性变得<类型的属性> _Name
  • 每个属性将是公共和只读
  • 对于每个属性会有一个相应的只读私有字段
  • 不会有任何其他属性或字段
  • 将有一个构造采取对应于每种类型的参数的一个参数,以相同的顺序为类型参数
  • 每个方法和属性将具有施加到它的DebuggerHiddenAttribute
  • 类型的名称将启动“<>”和含有“AnonymousType”

很少的,这是由规范但保证, - 所以它可以在编译器的下一个版本的所有变化,或者如果您使用单声道等

4

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

加上名称将是怪异的,这将是一个通用型;-p

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

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

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 
+0

不,没有编译器生成的属性 – JaredPar 2008-11-24 19:24:41

+0

@JaredPar:当然是有我的小测试。 – 2008-11-24 19:29:37

+1

[CompilerGenerated]将一个更大的匿名类型的宇宙区分开来。 – JaredPar 2008-11-24 19:31:44

1

对于扩展方法的目的是没有办法区分匿名类型。扩展方法通过指定编译时可命名类型的方法来工作。匿名类型是不可命名的,因此在编译时不可见。这使得它们与扩展方法不兼容。