2010-11-04 35 views
33

phép nói rằng tôi có các lớp sauGọi một phương pháp chung với một loại động

public class Animal { .... } 

public class Duck : Animal { ... } 

public class Cow : Animal { ... } 

public class Creator 
{ 
    public List<T> CreateAnimals<T>(int numAnimals) 
    { 
     Type type = typeof(T); 
     List<T> returnList = new List<T>(); 
     //Use reflection to populate list and return 
    } 
} 

Bây giờ trong một số mã sau, tôi muốn đọc những gì động vật để tạo ra.

Creator creator = new Creator(); 
string animalType = //read from a file what animal (duck, cow) to create 
Type type = Type.GetType(animalType); 
List<animalType> animals = creator.CreateAnimals<type>(5); 

Bây giờ vấn đề là dòng cuối cùng không hợp lệ. Có một số cách thanh lịch để làm điều này sau đó?

+2

Generics không thực sự là cách để đến đây, bạn chỉ cần tạo Danh sách thay vào đó và sử dụng Activator để tạo các lớp dẫn xuất. – Doggett

Trả lời

18

Không thực sự. Bạn cần sử dụng sự phản chiếu, về cơ bản. Generics thực sự nhằm mục đích gõ tĩnh chứ không phải là loại chỉ được biết đến tại thời điểm thực thi.

Để sử dụng phản ánh, bạn sẽ sử dụng Type.GetMethod để lấy định nghĩa phương thức, sau đó gọi MethodInfo.MakeGenericMethod(type), sau đó gọi nó như bất kỳ phương pháp nào khác.

46

Tôi không biết gì về tao nhã, nhưng cách để làm điều đó là:

typeof(Creator) 
    .GetMethod("CreateAnimals") 
    .MakeGenericMethod(type) 
    .Invoke(creator, new object[] { 5 }); 
+2

Mặc dù bạn sẽ không thể truyền nó như 'Danh sách 'hoặc' Danh sách 'v.v. trừ khi bạn đã biết loại tại thời gian biên dịch, mà bạn không có. Điều tốt nhất bạn có thể làm là truyền tới 'IList'. – LukeH

+0

@ LukeH, đúng, điểm tốt. –

+0

điều này rất xấu, nhưng đó là câu trả lời đúng – tofutim

1

Các phím này là MakeGenericType() và MakeGenericMethod(). Khi bạn đã hoạt động với các loại, bạn thực sự không thể quay lại gõ tĩnh. Những gì bạn có thể làm là tạo danh sách động, bằng cách sử dụng Activator.CreateInstance(typeof(List<>).MakeGenericType(type)) và sau đó tự động gọi phương thức chung bằng cách sử dụng các phương thức phản chiếu tương tự.

3

Hãy thử điều này:

public List<T> CreateAnimals<T>(int numAnimals) where T : Animal 
{ 
    Type type = typeof(T); 
    List<T> returnList = new List<T>(); 
    //Use reflection to populate list and return 
} 

Nó nên chắc chắn rằng các loại cho phép CreateAnimals kế thừa từ động vật. Sau đó, hy vọng, nó sẽ không có một vấn đề với List<animalType> animals = creator.CreateAnimals<type>(5);

+0

Điều đó không thực sự hữu ích nếu OP muốn đọc trong đó loại động vật để tạo ra từ một chuỗi. –

0
List<animalType> animals = 
creator.CreateAnimals<type>(5); 

Trong dòng trên từ ví dụ của bạn, animalTypetype đang chạy biến thời gian, chứ không phải các loại, vì vậy đây là tất nhiên vô nghĩa. Phiên bản chung chỉ có ý nghĩa, nếu bạn biết các loại tại thời gian biên dịch, ví dụ:

nơi bạn phải hạn chế loại phù hợp. Nếu các loại không được biết, bạn phải dựa hoàn toàn vào sự phản chiếu ...

Các vấn đề liên quan