2008-11-24 53 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

對於擴展方法的目的是沒有辦法區分匿名類型。擴展方法通過指定編譯時可命名類型的方法來工作。匿名類型是不可命名的,因此在編譯時不可見。這使得它們與擴展方法不兼容。