我有一个只能在运行时读取的类名和方法列表。有可能像这样动态创建一个类吗?我目前正在使用C#4.0。
答案 0 :(得分:3)
有些不清楚是否要在运行时定义类型,并且定义方法,或者是否要创建实例已经写入的类型,以及调用方法。
幸运的是两者都有可能。
第二种情况更有可能,所以你想看看反思(下图) - 但请注意,存在与此相关的性能损失(以及诸如“该方法采用什么参数”之类的小事变得非常重要)
对于第一种情况,您需要查看TypeBuilder
,但太多更复杂。另一种选择是CSharpCodeProvider
和动态装配加载,但是再次 - 不是任何延伸都是微不足道的。
using System;
namespace MyNamespace {
public class Foo {
public void Bar() {
Console.WriteLine("Foo.Bar called");
}
}
}
class Program {
static void Main() {
string className = "MyNamespace.Foo, MyAssemblyName",
methodName = "Bar";
Type type = Type.GetType(className);
object obj = Activator.CreateInstance(type);
type.GetMethod(methodName).Invoke(obj, null);
}
}
要包含参数(评论),请传递object[]
而不是null
:
using System;
namespace MyNamespace {
public class Foo {
public void Bar(string value) {
Console.WriteLine("Foo.Bar called: " + value);
}
}
}
class Program {
static void Main() {
string className = "MyNamespace.Foo, MyAssemblyName",
methodName = "Bar";
Type type = Type.GetType(className);
object obj = Activator.CreateInstance(type);
object[] args = { "hello, world" };
type.GetMethod(methodName).Invoke(obj, args);
}
}
如果您正在执行此操作批次(对于相同的方法),有一种方法可以通过类型化的委托来提高性能,但这对于偶尔没有太多帮助>电话。
答案 1 :(得分:0)
您可以直接使用.net框架中的IL发射功能来实现此目的。您需要学习IL才能在运行时动态生成类型信息 - 这不是为了佯攻。
Introduction to Creating Dynamic Types with System.Reflection.Emit
答案 2 :(得分:0)
我无法回答您的问题,我会回答您可能想问的一些问题。
不确定。首先是简单的方法。使用if
语句:
var className = "MyClass";
var methodName = "MyMethod";
if (className == typeof(MyClass).Name) {
var instance = new MyClass();
if (methodName == "MyMethod")
instance.MyMethod();
if (methodName == "MyOtherMethod")
instance.MyOtherMethod();
}
或者,您可以使用Activator.CreateInstance
为您创建课程实例。
var className = "MyClass";
var methodName = "MyMethod";
//Get a reference to the Assembly that has the desired class. Assume that all classes that we dynamically invoke are in the same assembly as MyClass.
var assembly = typeof(MyClass).Assembly;
//Find the type that we want to create
var type = assembly.GetTypes().FirstOrDefault(t=>t.Name == className);
if(type != null) {
//Create an instance of this type.
var instance = Activator.CreateInstance(type);
//Find the method and call it.
instance.GetType().GetMethod(methodName).Invoke(instance);
}
是的,你可以,但这很难。如果您是一位经验丰富的C#程序员,知道一点C ++和汇编,那么您应该能够克服它。如果没有,请不要打扰。
Microsoft提供了一个库,用于发出名为surpose,IL.Emit
的中间语言代码。很少有问题需要使用这种方法,其中包括模拟对象生成和依赖注入的某些方面。你的问题很可能以另一种方式得到更好的解决。