2010-07-28 19 views
17

Tôi có một dll chứa một số lớp mà tất cả đều được kế thừa từ một lớp CommandBase. Tôi đang cố gắng để có được trường hợp của tất cả các lớp này (CommandA, CommandB, CommandC, vv ...) bằng cách sử dụng phản ánh trong C# để tôi có thể gọi một phương pháp cụ thể trên mỗi một. Dưới đây là những gì tôi có cho đến thời điểm này:Sử dụng sự phản chiếu để có được tất cả các lớp của một kiểu cơ sở nhất định trong dll

//get assemblies in directory. 
string folder = Path.Combine(HttpContext.Current.Server.MapPath("~/"), "bin"); 
var files = Directory.GetFiles(folder, "*.dll"); 
//load each assembly. 
foreach (string file in files) 
{ 
    var assembly = Assembly.LoadFile(file); 
    if (assembly.FullName == "MyCommandProject") 
    { 
    foreach (var type in assembly.GetTypes()) 
    { 
     if (!type.IsClass || type.IsNotPublic) continue; 
     if(type is CommandBase) 
     { 
     var command = Activator.CreateInstance(type) as CommandBase; 
     } 
    } 
    } 
} 

Tôi đang gặp phải 2 vấn đề. Vấn đề thứ nhất là dòng "if (type is CommandBase") đưa ra cảnh báo sau:

Biểu thức đã cho không bao giờ được cung cấp Loại CommandBase.

Vấn đề thứ hai là tôi không thể tìm ra cách để có được một thể hiện của đối tượng thực tế (CommandA, CommandB, vv ...), chỉ cần chuyển đổi nó sang CommandBase là không đủ.

+0

Dòng cuối cùng của bạn không tạo đúng trường hợp? 'Với Activator.CreateInstance()', bạn nên có một thể hiện của CommandA, CommandB ... lớp (tùy thuộc vào 'loại'), không? –

+0

Activation.CreateInstance() trả về đối tượng kiểu. – Justin

+0

Có nhưng nó trả về một đối tượng thuộc loại bạn đã cung cấp. Bạn có thể lưu trữ nó trong một "đối tượng" var hoặc một "CommandBase" var, nó vẫn sẽ là một CommandA, CommandB, vv dụ. Bạn có thể truyền sau này thành loại "thực". Tôi không có Visual Studio để kiểm tra nhưng tôi không thấy vấn đề là gì. –

Trả lời

29

Đây là phương pháp tôi sử dụng để tải lên dựa trên giao diện.

private static List<T> GetInstances<T>() 
{ 
     return (from t in Assembly.GetExecutingAssembly().GetTypes() 
       where t.GetInterfaces().Contains(typeof (T)) && t.GetConstructor(Type.EmptyTypes) != null 
       select (T) Activator.CreateInstance(t)).ToList(); 
} 

Và đây là chức năng tương tự kéo trở lại dựa trên lớp cơ sở.

private static IList<T> GetInstances<T>() 
{ 
     return (from t in Assembly.GetExecutingAssembly().GetTypes() 
         where t.BaseType == (typeof(T)) && t.GetConstructor(Type.EmptyTypes) != null 
         select (T)Activator.CreateInstance(t)).ToList(); 
} 

Tất nhiên, nó sẽ cần được sửa đổi một chút để trỏ vào tham chiếu bạn đang tải.

+0

Cảm ơn, nhưng vì một lý do nào đó nó chỉ trả về lớp CommandBase, không phải các lớp thừa hưởng từ nó. Ngoài ra, nếu tôi gọi nó là "GetInstances ()", nó cung cấp cho tôi một danh sách các đối tượng CommandBase, không phải đối tượng tôi cần - CommandA, CommandB, v.v. Có vẻ như tôi cần sử dụng giao diện để làm việc này . – Justin

+0

Đã thêm một hàm thứ hai để bạn sử dụng cho lớp CommandBase của mình. Bạn nên lấy danh sách các thể hiện của các lớp kế thừa từ CommandBase. Hoạt động khi tôi ném nó vào một thử nghiệm đoạn mã đơn giản. –

+0

Tôi đã chuyển sang sử dụng giao diện và sử dụng ví dụ mã đầu tiên của bạn, cảm ơn! – Justin

2

Đó là do biến số type của bạn là Type, không phải là CommandBase.

Bạn muốn

if(type == typeof(CommandBase)) 

(Cảm ơn Greg cho việc sửa chữa)

+1

Sẽ không phải là 'if (type == typeof (CommandBase))'? – Greg

+1

Điều này sẽ không hoạt động đối với các lớp dẫn xuất. –

+1

Nó đã kết thúc được "==" thay vì "là" nhưng yeah mà làm việc, cảm ơn. Lời khuyên nào về vấn đề thứ 2 của tôi? – Justin

7

Thay đổi type is CommandBase-typeof(CommandBase).IsAssignableFrom(type)

+0

+1 Bạn nhận được đúng –

+0

+1 Tôi không thấy kết quả của bạn khi tôi đang gõ, tuy nhiên msdn này nói "Nếu IsSubclassOf là trò chuyện của IsAssignableFrom. Đó là, nếu t1.IsSubclassOf (t2) là đúng, thì t2. IsAssignableFrom (t1) cũng đúng. " vì vậy cả hai chúng tôi đều bình đẳng, tôi đã chỉ ra câu trả lời của câu trả lời là và ==. –

6

Bạn phải thay đổi

if(type is CommandBase) 

để

if(type.IsSubclassOf(typeof(CommandBase))) 

Nếu IsSubclassOf là trò chuyện của IsAssignableFrom. Tức là, nếu t1.IsSubclassOf (t2) là đúng, thì t2.IsAssignableFrom (t1) cũng đúng.

+0

Tức là, ngoại trừ câu trả lời của tôi, câu trả lời đúng từ đầu. :), nhưng tôi đang cho bạn một +1 cho đúng và bởi vì tôi đã không bao giờ nhận thấy phương pháp IsSubclassOf, vì tôi chỉ sử dụng IsAssignableFrom. –

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