如何dynamic创build使用reflection的通用C#对象?

在C#中我有以下对象:

public class Item { } public class Task<T> { } public class TaskA<T> : Task<T> { } public class TaskB<T> : Task<T> { } 

我想使用C#reflection( Activator.CreateInstance )dynamic创buildTaskA或TaskB。 不过,我不知道types之前,所以我需要dynamic创buildTaskA基于像“namespace.TaskA”或“namespace.TaskAB”string。

看看这篇文章和这个简单的例子 。 快速翻译相同的类…

 var d1 = typeof(Task<>); Type[] typeArgs = { typeof(Item) }; var makeme = d1.MakeGenericType(typeArgs); object o = Activator.CreateInstance(makeme); 

根据你的编辑:对于这种情况,你可以做到这一点…

 var d1 = Type.GetType("GenericTest.TaskA`1"); // GenericTest was my namespace, add yours Type[] typeArgs = { typeof(Item) }; var makeme = d1.MakeGenericType(typeArgs); object o = Activator.CreateInstance(makeme); 

为了查看我在哪里find了通用类名称的backtick1,请参阅这篇文章 。

注意:如果您的generics类接受多种types,则在省略types名称时必须包含逗号,例如:

 Type type = typeof(IReadOnlyDictionary<,>); 

事实上,你将无法写出最后一行。

但是你可能不想创build这个对象,只是为了创build它。 你可能想要在你新创build的实例上调用一些方法。

然后你需要一个像界面一样的东西:

 public interface ITask { void Process(object o); } public class Task<T> : ITask { void ITask.Process(object o) { if(o is T) // Just to be sure, and maybe throw an exception Process(o as T); } public void Process(T o) { } } 

并用以下方式调用它:

 Type d1 = Type.GetType("TaskA"); //or "TaskB" Type[] typeArgs = { typeof(Item) }; Type makeme = d1.MakeGenericType(typeArgs); ITask task = Activator.CreateInstance(makeme) as ITask; // This can be Item, or any type derived from Item task.Process(new Item()); 

在任何情况下,您都不会被静态地转换成您事先不知道的types(在这种情况下为“makeme”)。 ITask允许你达到你的目标types。

如果这不是你想要的,你可能需要更具体一些你想要达到的目标。

在我看来,你的示例代码的最后一行应该是:

 Task<Item> itsMe = o as Task<Item>; 

还是我错过了什么?

确保你这样做是有原因的,像下面这样简单的函数将允许静态types的input,并允许你的IDE执行诸如“查找引用”和重构 – >重命名。

 public Task <T> factory (String name) { Task <T> result; if (name.CompareTo ("A") == 0) { result = new TaskA (); } else if (name.CompareTo ("B") == 0) { result = new TaskB (); } return result; } 

我知道这个问题已经解决了,但是为了读者的利益, 如果将所有types都作为string来处理,则可以将其作为一个整数进行操作:

 IYourInterface o = (Activator.CreateInstance(Type.GetType("Namespace.TaskA`1[OtherNamespace.TypeParam]") as IYourInterface); 

每当我做了这样的事情,我有一个接口,我想要后续的代码利用,所以我已经铸造了创build的实例接口。