2017-04-11 67 views
3

如何在元組中迭代項時,我不知道在編譯時元組是由什麼類型組成的?我只需要一個IEnumerable對象(用於序列化)。如何迭代元組項

private static IEnumerable TupleToEnumerable(object tuple) 
{ 
    Type t = tuple.GetType(); 
    if (t.IsGenericType && t.GetGenericTypeDefinition() == typeof(Tuple<,>)) 
    { 
     var x = tuple as Tuple<object, object>; 
     yield return x.Item1; 
     yield return x.Item2; 
    } 
} 
+0

什麼是你發出 –

+0

'VAR值= tuple.GetType()。GetProperties中(),選擇(屬性=> property.GetValue(元組))' – Fabio

回答

2

您可以通過反射與Type.GetProperties

var values = tuple.GetType().GetProperties().Select(property => property.GetValue(tuple)); 
01訪問屬性及其值

所以,你的方法是非常簡單的Linq查詢

private static IEnumerable TupleToEnumerable(object tuple) 
{ 
    // You can check if type of tuple is actually Tuple 
    return tuple.GetType() 
       .GetProperties() 
       .Select(property => property.GetValue(tuple)); 
} 
3

這裏的一個問題是,你必須處理多個Tuple類型:(我假設你想這與元組工作與項目的任意數字)Tuple<T1, T2>Tuple<T1, T2, T3>

這樣做,看看是否該類型的名稱始於System.Tuple的有點哈克的方式:

public static IEnumerable TupleToEnumerable(object tuple) 
{ 
    Type t = tuple.GetType(); 

    if (t.IsGenericType && t.GetGenericTypeDefinition().FullName.StartsWith("System.Tuple")) 
    { 
     for (int i = 1;; ++i) 
     { 
      var prop = t.GetProperty("Item" + i); 

      if (prop == null) 
       yield break; 

      yield return prop.GetValue(tuple); 
     } 
    } 
} 

如果你不喜歡的FullName.StartsWith(...)的hackyness你可以把它更加類型安全像這樣:

public static IEnumerable TupleToEnumerable(object tuple) 
{ 
    Type t = tuple.GetType(); 

    if (isTupleType(t)) 
    { 
     for (int i = 1;; ++i) 
     { 
      var prop = t.GetProperty("Item" + i); 

      if (prop == null) 
       yield break; 

      yield return prop.GetValue(tuple); 
     } 
    } 
} 

private static bool isTupleType(Type type) 
{ 
    if (!type.IsGenericType) 
     return false; 

    var def = type.GetGenericTypeDefinition(); 

    for (int i = 2;; ++i) 
    { 
     var tupleType = Type.GetType("System.Tuple`" + i); 

     if (tupleType == null) 
      return false; 

     if (def == tupleType) 
      return true; 
    } 
} 
0

按照預期的代碼不工作,因爲你是在您的元組使用預期的Tuple<object,object>完全匹配的是不是這種情況

你可以試試下面的更通用的(如果你希望永遠是兩個項目)

class Program 
    { 
     static void Main(string[] args) 
     { 
      Tuple<string, string> tuples = new Tuple<string, string>("test","test"); 
      foreach (string item in TupleToEnumerable<string>(tuples)) 
      { 
       Console.WriteLine(item); 

      } 
     } 

     private static IEnumerable<T> TupleToEnumerable<T>(object tuple) 
     { 
      Type t = tuple.GetType(); 
      if (t.IsGenericType && t.GetGenericTypeDefinition() == typeof(Tuple<,>)) 
      { 
       var x = tuple as Tuple<T, T>; 
       yield return x.Item1; 
       yield return x.Item2; 
      } 
     } 
    } 
+0

TupleToEnumerable <_string_>(元組) - 不能像這樣使用它。我不知道在編譯時什麼類型。 –

+0

你必須使用反射,但在性能成本 –

+1

這需要兩個屬性具有相同的類型,這可能並非總是如此。 –