使用泛型类型创建类的实例,并在运行时从对象的字符串名称调用相同泛型类型的方法

时间:2016-05-18 18:07:08

标签: c# generics dynamic activator

我有一个泛型类,它有一个泛型方法,它使用与实例化对象时传递的类型相同的类型。在运行时,我只知道我需要通过该对象名的字符串表示传入的对象的名称。我已经阅读了一些关于使用Activator和可能使用动态的东西,但我无法理解我需要如何使用它。这是我的泛型类的代码片段:

public class MyClass<T> where T : class, new()
{ 
        public IList<T> MyMethod(Stream stream)
        {
             var data = new List<T>();
             // stuff to create my list of objects
             return data;
        }
}

我需要根据我作为字符串传入的对象的名称从MyMethod()方法返回我的IList。

我可以在字符串上执行切换/大小写,然后使用对“真实”对象的引用来实例化案例中的MyClass,但我想知道是否有更好(更短更清洁)的方法

TIA

3 个答案:

答案 0 :(得分:8)

你的包装得到了以下签名:

public class MyClass<T> where T : class, new()

它基本上说&#34; T需要是一个类,并且有一个默认的构造函数&#34; 。有趣的部分是关于默认构造函数。这意味着该类必须具有不带参数的构造函数。

它告诉.NET您可以调用:

var obj = new T();

所以第一步就是这样做:

public class MyClass<T> where T : class, new()
{ 
        public IList<T> MyMethod(Stream stream)
        {
             var data = new List<T>();

             //this
             var obj = new T();

             return data;
        }
}

接下来你想调用一个方法。这是在reflection的帮助下完成的。

一个简单的例子是:

var obj = new T();

//get type information
var type = obj.GetType();

//find a public method named "DoStuff"
var method = type.GetMethod("DoStuff");

// It got one argument which is a string.
// .. so invoke instance **obj** with a string argument
method.Invoke(obj, new object[]{"a string argument"});

<强>更新

我错过了重要部分:

  

我需要根据我以字符串形式传入的对象的名称,从MyMethod()方法返回我的IList。

如果类型在与执行代码相同的程序集中声明,则可以传递完整的类型名称,如Some.Namespace.ClassName" to Type.GetType()`:

var type = Type.GetType("Some.Namespace.ClassName");
var obj = Activator.CreateInstance(type);

如果在另一个程序集中声明了类,则需要指定它:

var type = Type.GetType("Some.Namespace.ClassName, SomeAsseblyName");
var obj = Activator.CreateInstance(type);

其余的基本相同。

如果您只有类名,则可以遍历程序集以找到正确的类型:

var type = Assembly.GetExecutingAssembly()
                   .GetTypes()
                   .FirstOrDefault(x => x.Name == "YourName");
var obj = Activator.CreateInstance(type);

答案 1 :(得分:2)

听起来您想要创建泛型类型,以便您可以创建它的实例。

//Assuming "typeName" is a string defining the generic parameter for the
//type you want to create.
var genericTypeArgument = Type.GetType(typeName);
var genericType = typeof (MyGenericType<>).MakeGenericType(genericTypeArgument);
var instance = Activator.CreateInstance(genericType);

这假定您已经知道泛型类型是什么,而不是类型参数那个泛型类型。换句话说,您正在尝试确定<T>是什么。

答案 2 :(得分:1)

使用反射。将MyMethod设为静态。请参阅以下代码:

public object run(string typename, Stream stream)
{
        var ttype = Assembly
             .GetExecutingAssembly()
             .GetTypes()
             .FirstOrDefault(x => x.Name == typename);
        MethodInfo minfo = typeof(MyClass)
             .GetMethod("MyMethod", BindingFlags.Static | BindingFlags.Public);
        return minfo
             .MakeGenericMethod(ttype)
             .Invoke(null, new object[] { stream });
}