2017-04-11 123 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

这需要两个属性具有相同的类型,这可能并非总是如此。 –