2011-04-06 10 views
13

EDITARComprobación de IEnumerable <T> con la reflexión

La versión básica de esta pregunta es, si tengo alguna object o, ¿cómo puedo comprobar para ver si o es de algún tipo que implementa IEnumerable<string>con la reflexión? La pregunta original es mucho más específica, pero una respuesta a lo anterior sería igual de buena. Lo siento si he dado demasiada detalle sobre esta cuestión

FIN EDITAR

La siguiente es una artificiosa ValueInjecter POC. Todo funciona bien excepto el método isCollectionMapping en la parte inferior. Estoy intentando que sea verdadero si y solo si las propiedades de origen y destino son cualquier objeto que implemente IEnumerable<respectiveTypes>.

He intentado IsAssignableFrom y también IsInstanceOfType, pero ninguno parece funcionar.

Todo lo demás funciona ya que cuando elimino el comentario de la segunda línea del método para verificar explícitamente las propiedades del nombre "Hijos", funciona bien.

Nota - Sé que hay problemas con este ejemplo. A saber, estoy tratando de verificar cualquier antiguo IEnumerable<> pero, sin embargo, siempre sabiendo lo suficiente como para devolver List<>; es solo una prueba tonta de concepto en este punto.

[TestClass] 
public class UnitTest1 { 

    [TestMethod] 
    public void TestMethod1() { 
     List<string> strings = new List<string>(); 

     Subject S = new Subject() { 
      id = 1, 
      SubjectName = "S1", 
      Children = { new Subject() { id = 2, SubjectName = "S1a" }, 
         new Subject() { id = 3, SubjectName = "S1b", Children = { new Subject() { id = 4} } } } 
     }; 

     SubjectViewModel VM = (SubjectViewModel)new SubjectViewModel().InjectFrom<CollectionToCollection>(S); ; 


     Assert.AreEqual(2, VM.Children.Count); 
     Assert.AreEqual(1, VM.Children.Single(s => s.id == 3).Children.Count); 
    } 
} 


public class Subject { 
    public Subject() { 
     Children = new List<Subject>(); 
    } 

    public string SubjectName { get; set; } 
    public int id { get; set; } 

    public List<Subject> Children { get; set; } 
} 

public class SubjectViewModel { 
    public SubjectViewModel() { 
     Children = new List<SubjectViewModel>(); 
    } 

    public string SubjectName { get; set; } 
    public int id { get; set; } 

    public List<SubjectViewModel> Children { get; set; } 
} 

public class CollectionToCollection : Omu.ValueInjecter.ConventionInjection { 
    protected override bool Match(ConventionInfo c) { 
     return c.TargetProp.Name == c.SourceProp.Name; 
    } 

    protected override object SetValue(ConventionInfo c) { 
     if (isCollectionMapping(c)) 
      return (c.SourceProp.Value as IEnumerable<Subject>).Select(s => (SubjectViewModel)(new SubjectViewModel().InjectFrom<CollectionToCollection>(s))).ToList(); 
     else 
      return c.SourceProp.Value; 
    } 

    private bool isCollectionMapping(ConventionInfo c) { 
     return c.SourceProp.Value.GetType().IsInstanceOfType(typeof(IEnumerable<Subject>)) && c.TargetProp.Value.GetType().IsAssignableFrom(typeof(IEnumerable<SubjectViewModel>)); 

     //return c.SourceProp.Name == "Children" && c.TargetProp.Name == "Children"; 
    } 
} 

Respuesta

27

Si tengo algún objeto o, ¿cómo iba a comprobación para ver si es o de algún tipo que implementa IEnumerable<string>?

tan simple como:

o is IEnumerable<string> 

Por cierto, el código actual no está funcionando porque es revertir la prueba de la relación transferibilidad (como si el método se llama IsAssignableTo), es decirSe asume que:

Bar bar = ... 
Foo foo = bar 

implica:

typeof(Bar).IsAssignableFrom(typeof(Foo)) // wrong 

En realidad, la implicación real es que:

typeof(Foo).IsAssignableFrom(typeof(Bar)) 

Es decir, que estoy tratando de comprobar si hay alguna anterior IEnumerable<>:

En este caso, es necesario comprobar si el tipo implementa una versión construida de la interfaz genérica:

o.GetType() 
.GetInterfaces() 
.Any(t => t.IsGenericType 
     && t.GetGenericTypeDefinition() == typeof(IEnumerable<>)) 
10

La versión básica de esta pregunta es, si tengo algún objeto o, ¿cómo puedo comprobar para ver si o es de algún tipo que implementa IEnumerable<string>?

De esta manera:

object o = whatever; 
bool isSequenceOfStrings = o is IEnumerable<string>; 
+0

Parece que realmente me cuesta mucho encontrar un equilibrio entre demasiada información y muy poco. Necesito hacerlo con reflexión. Perdón por la confusión, Eric. :) –

+0

@ Adam: ¿Entonces cuál es la pregunta? ¿La pregunta es "si tengo algún tipo de objeto t ¿cómo verificaría si t implementa IEnumerable ?" ¿O es la pregunta "si tengo algún tipo de objeto t entonces cómo verificaría si t es IEnumerable ?" ¿O es la pregunta "si tengo algún tipo de objeto t entonces cómo verificaría si T es convertible a IEnumerable para cualquier T?" o ... Esas son todas preguntas diferentes. Obtendrá la respuesta que desee cuando haga la pregunta que realmente le interese. –

+0

¿Por qué necesitas hacerlo con reflexión? –

5

que podría haber perdido algo (no leyó el ejemplo de código entero), pero doesn' Parece que necesitas reflexión aquí.

¿Qué tal usando:

if (c.SourceProp.Value is IEnumerable<Subject>) 
    return true; 

Si usted no sabe el tipo específico, utilice los genéricos:

public bool MyFunction<T>(...) 
{ 
    if (c.SourceProp.Value is IEnumerable<T>) 
     return true; 
} 

O si necesita usar la interfaz, hacerlo de esta manera (guarda un yeso):

var enumerable = c.SourceProp.Value as IEnumerable<string>; 
if (enumerable != null) 
{ 
    // Use IEnumerable<string> 
    return true; 
} 

return false; 
+0

Gracias, sí, lo simple habría funcionado. No estoy seguro de cómo me perdí eso. +1 –

Cuestiones relacionadas