使用泛型类型创建 class 的实例,并在运行时从对象的字符串名称调用相同泛型类型的方法
Create instance of class with generic type and call method of same generic type from string name of object at runtime
我有一个泛型 class,它有一个泛型方法,该方法使用与实例化对象时传递的类型相同的类型。在运行时,我只会知道我需要通过该对象名称的字符串表示形式传入的对象的名称。我已经阅读了一些关于使用 Activator 和可能使用 dynamic 的内容,但我无法理解我需要如何完成这项工作。这是我的通用 class 的片段:
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() 方法 return 我的 IList。
我可以只对字符串做一个 switch/case 然后在 case 中实例化 MyClass 并引用 "real" 对象,但我想知道是否有更好的(更短和更清洁)的方法。
TIA
您的包装器具有以下签名:
public class MyClass<T> where T : class, new()
基本上是说"T needs to be a class and have a default constructor"。有趣的部分是关于默认构造函数。这意味着 class 必须有一个不带参数的构造函数。
它告诉 .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"});
更新
我错过了重要的部分:
I need to return my IList from the MyMethod() method based on the name of the object I'm passing in as a string.
如果类型是在与执行代码相同的程序集中声明的,您可以只传递完整的类型名称,例如 Some.Namespace.ClassName" to
Type.GetType()`:
var type = Type.GetType("Some.Namespace.ClassName");
var obj = Activator.CreateInstance(type);
如果 class 在另一个程序集中声明,您需要指定它:
var type = Type.GetType("Some.Namespace.ClassName, SomeAsseblyName");
var obj = Activator.CreateInstance(type);
其余大同小异
如果您只有 class 名称,您可以遍历程序集以找到正确的类型:
var type = Assembly.GetExecutingAssembly()
.GetTypes()
.FirstOrDefault(x => x.Name == "YourName");
var obj = Activator.CreateInstance(type);
使用反射。使 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 });
}
听起来您想创建泛型类型以便创建它的实例。
//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);
这假定您已经知道泛型类型是什么,但不知道泛型类型 for 的类型参数。换句话说,您正在尝试确定 <T>
是什么。
我有一个泛型 class,它有一个泛型方法,该方法使用与实例化对象时传递的类型相同的类型。在运行时,我只会知道我需要通过该对象名称的字符串表示形式传入的对象的名称。我已经阅读了一些关于使用 Activator 和可能使用 dynamic 的内容,但我无法理解我需要如何完成这项工作。这是我的通用 class 的片段:
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() 方法 return 我的 IList。
我可以只对字符串做一个 switch/case 然后在 case 中实例化 MyClass 并引用 "real" 对象,但我想知道是否有更好的(更短和更清洁)的方法。
TIA
您的包装器具有以下签名:
public class MyClass<T> where T : class, new()
基本上是说"T needs to be a class and have a default constructor"。有趣的部分是关于默认构造函数。这意味着 class 必须有一个不带参数的构造函数。
它告诉 .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"});
更新
我错过了重要的部分:
I need to return my IList from the MyMethod() method based on the name of the object I'm passing in as a string.
如果类型是在与执行代码相同的程序集中声明的,您可以只传递完整的类型名称,例如 Some.Namespace.ClassName" to
Type.GetType()`:
var type = Type.GetType("Some.Namespace.ClassName");
var obj = Activator.CreateInstance(type);
如果 class 在另一个程序集中声明,您需要指定它:
var type = Type.GetType("Some.Namespace.ClassName, SomeAsseblyName");
var obj = Activator.CreateInstance(type);
其余大同小异
如果您只有 class 名称,您可以遍历程序集以找到正确的类型:
var type = Assembly.GetExecutingAssembly()
.GetTypes()
.FirstOrDefault(x => x.Name == "YourName");
var obj = Activator.CreateInstance(type);
使用反射。使 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 });
}
听起来您想创建泛型类型以便创建它的实例。
//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);
这假定您已经知道泛型类型是什么,但不知道泛型类型 for 的类型参数。换句话说,您正在尝试确定 <T>
是什么。