2017-05-25 25 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