如何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的实例接口。