2017-05-25 62 views
0

我想调用一些方法从不同的存储库,并具有相同的类型List<>作为结果,但我不知道如何施放没有硬编码的结果,以及如何使用foreach对这个结果,这里的例子如下:反射:如何从使用反射调用的方法获得结果(并对其进行foreach)?

class Person 
{ 
    public string Name { get; set; } 
} 

class Animal 
{ 
    public string Name { get; set; } 
} 

class PersonRepository 
{ 
    public List<Person> GetPersons() 
    { 
      List<Person> list = new List<Person>(); 

      //Some processing... 

      return list; 
    } 
} 

class AnimalRepository 
{ 
    public List<Animal> GetAnimals() 
    { 
     List<Animal> list = new List<Animal>(); 

     //Some processing... 

     return list; 
    } 
} 

public class ReflectionClass 
{ 
    public List<T> GetResultFromMethodInvoked<T>(string entityName, string repositoryName, string methodName) 
    { 
     List<T> lists = new List<T>(); 
     Type entity_type = Type.GetType("Entities." + entityName + " ,Entities"); 
     Type repository = Type.GetType("Crud." + repositoryName + ", Crud"); 
     MethodInfo method = repository.GetType().GetMethod(methodName); 


     var r= method.Invoke(repository, parameters); 


     Convert.ChangeType(r, typeof(List<>).MakeGenericType(new Type[] { entity_type })); 

     lists = (List<T>)r; 

     return lists; 
    } 
} 

class Program 
{ 
    static void Main(string[] args) 
    { 
     ReflectionClass reflection = new ReflectionClass(); 
     /* Should have List<Person> as RESULT */ 
     reflection.GetResultFromMethodInvoked("Person", "PersonRepository", "GetPersons"); 

     /* Should have List<Animal> as RESULT */ 
     reflection.GetResultFromMethodInvoked("Animal", "AnimalRepository", "GetAnimals"); 
    } 
} 
+1

这是不可能的,你不能让**编译器**推断你在** runtime **处提供的类型。你需要在**编译时提供泛型类型参数 - 使用强类型的时候。 – HimBromBeere

+0

但是,您当然可以将您的结果转换为非泛型的“IEnumerable”接口并重复此操作。或者创建一个接口,让列表中所有可能的类型实现并转换为List 。 – HimBromBeere

+0

您好@HimBromBeere,我不确定要理解好,我是C#中的新成员,请给我举一个例子来说明您提到的内容。非常感谢 –

回答

0

在你的代码使用泛型public List<T> GetResultFromMethodInvoked<T>(string entityName, string repositoryName, string methodName)这样:

ReflectionClass reflection = new ReflectionClass(); 
/* Should have List<Person> as RESULT */ 
List<Person> result = reflection.GetResultFromMethodInvoked<Person>("Person", "PersonRepository", "GetPersons"); 
0

您不容做到这一点,因为编译器,因为没有知识,你的运行 -string "Person"意味着Person类型。您不能期望编译器推断运行时提供的类型(例如,通过其名称)。

所以你有三个选择。

  1. 你已经提到过这一点,转换为实际的列表类型,例如, List<Person>
  2. alternativly让所有类型的列表可能包含来自一个共同的接口继承和强制转换为接口类型

    interface MyInterface 
    { 
        public string Name { get; set; } 
    } 
    class Person : MyInterface 
    { 
        public string Name { get; set; } 
    } 
    class Animal : MyInterface 
    { 
        public string Name { get; set; } 
    } 
    

    现在使用的界面为你的目录列表:

    var result = reflection.GetResultFromMethodInvoked<MyInterface>("Person", "PersonRepository", "GetPersons"); 
    foreach(var o in result) 
        Console.WriteLine(o.Name); 
    
  3. 都省略强类型和去与非通用Enumerable -class并重复这一点:

    var result = (Enumerable) reflection.GetResultFromMethodInvoked("Person", "PersonRepository", "GetPersons"); 
    foreach(var o in result) ... 
    

    为了实现这个功能,你的方法当然也应该是非泛型的,因为你不能在该方法之外真正使用泛型类型。

+0

@AbdelatifLatrach正如我已经说过的一个geeric类型参数(这是括号内的东西,无论是'(MyType)结果'还是DoSomething ()'是*编译*时间信息。但是它是一个运行时信息,这意味着当你真的执行你的程序时就会对它进行评估,所以简短的答案是:不,这是不可能的。 – HimBromBeere