创建和使用类的实例,其类名仅在运行时已知

时间:2010-05-10 03:20:01

标签: c# reflection

我有一个只能在运行时读取的类名和方法列表。有可能像这样动态创建一个类吗?我目前正在使用C#4.0。

3 个答案:

答案 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的中间语言代码。很少有问题需要使用这种方法,其中包括模拟对象生成和依赖注入的某些方面。你的问题很可能以另一种方式得到更好的解决。