如何在C#中将类名作为参数使用

54

我想要做的是自动创建一些对象。

在Java中,可以将类作为参数传递,例如

Class A{

}


Object createObjectBy(class clazz){
       // .. do construction work here
}

when using it, just ---> createObjectBy(A.class)

它对很多事情都有好处。

那么,在C#中我该如何做类似的事情呢?


3
你究竟想做什么?使用不同的语法,C#可能有更好的方法实现相同的目的。 - Asad
1
你可以使用泛型来实现类似的功能,但是你想做什么,简单的 "new A()" 不能满足吗? - Daniel Pratt
获取方法名称请参见如何找到调用当前方法的方法? - Michael Freidgeim
4个回答

63
Object createObjectBy(Type clazz){
   // .. do construction work here
    Object theObject = Activator.CreateInstance(clazz);
    return theObject;
}

使用方法:

createObjectBy(typeof(A));

或者你可以直接使用Activator.CreateInstance :-)


1
只是提醒一下,使用这种方法时,你的调用代码应该像这样:Class B = (Class) CreateObjectBy(tyepof(A)); - Wagner Silveira
3
如果类型没有无参数的构造函数,那么这将失败。 - Pierre-Alain Vigeant
嘿,Aviad P,如果类A有一个参数怎么办?我该如何将它传递给对象theObject? - Benedito
@Benedito,CreateInstance有一个重载函数可以接受构造函数的参数:https://msdn.microsoft.com/zh-cn/library/wcxyzt4d(v=vs.110).aspx - Aviad P.
是的,我看到了。但是在那之后,我又发现了另一个问题。A类有一些方法。我想在创建实例的方法中使用其中的一个方法。但是Visual Studio指出编译错误,告诉我“theObject”没有这样的方法。你知道如何解决吗?或者有什么地方可以查找相关信息吗? - Benedito
你需要使用反射来实现这个,可以在运行时通过字符串调用方法名。请参考这个stackoverflow的答案:https://dev59.com/5HA75IYBdhLWcg3wxsJn#3110313 - 然而,有一种更好的方法可以在编译时使用接口来实现,而不是在运行时使用Activator或反射。 - Aviad P.

44

最理想的方式是使用泛型。

类型在设计时已知

public static T CreateInstance<T>() where T: new()
{
    // Do some business logic
    Logger.LogObjectCreation(typeof(T));

    // Actualy instanciate the object
    return new T();
}

一个调用示例看起来像这样:
var employee = CreateInstance<Employee>();

运行时类型未知

如果对象的类型在运行时未知,例如通过插件系统,您需要使用Type类:

public static object CreateInstance(Type type)
{
    // Do some business logic
    Logger.LogObjectCreation(type);

    // Actualy instanciate the object
    return Activator.CreateInstance(type);
}

一个调用示例可能如下所示。
var instance = CreateInstance(someType);

性能

当然,使用关键字new实例化一个对象是最快的方法。除非你可以通过缓存来重用对象,而不需要实例化。

如果你只能接受第二种类型未知的方法,则有一些替代方案来替换Activator.CreateInstance。虽然该文章建议使用lambda表达式,但你应该考虑以下因素:

  • 你的未知对象在短时间内需要多次实例化吗?或者你只需要创建一次

如果你只需创建对象一次,请继续使用Activator.CreateInstance方法。如果你需要在短时间内多次创建对象,请尝试使用lambda表达式的方法。最后一种方法类似于编译正则表达式与即时正则表达式之间的区别。


对于那些不理解 T: new() 是什么意思的人: http://www.codeproject.com/Articles/16831/Constraints-in-Generics - RAY

7
使用Type类。你可以通过调用它来返回一个实例。
obj.GetType();

或者没有对象实例

typeof(className);

我希望这能有所帮助。

6

C#不支持这个。但是你想做什么?

你可能可以使用:

createObjectBy(Type type);

或者

createObjectBy<T>();

1
通常我会同时使用这两种方法,其中第二种只是将第一种方法转发。第一种方法允许从反射中轻松调用和懒惰传递,第二种方法允许直接从代码中轻松(强类型)调用。 - Travis Gockel
经常有人因为不明原因而给你点踩,甚至没有勇气在评论区解释原因。 - Thameem

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接