动态获取对象类型然后创建它的新实例的C#方式是什么?
E.g。如何实现遵循Java代码的结果,但在C#中:
MyClass x = (MyClass) Class.forName("classes.MyChildClass").newInstance();
答案 0 :(得分:8)
看看csharp-examples.net/reflection-examples。基本上,您必须使用typeof()
和Activator.createInstance()
。
答案 1 :(得分:5)
这个问题有两个部分
如何获取与名称对应的Type
?
有时您可以使用Type.GetType(string)
。但除非类型在mscorlib或正在执行的程序集中,否则您需要在名称中指定程序集的名称。
如何创建给定的类型?
Activatior.CreateInstance
是这部分的答案。
但是在你的代码中你已经知道了这个类,因为你可以转换为MyClass
。所以这个问题没有多大意义。
答案 2 :(得分:4)
简单示例:
namespace Your.Namespace
{
public class Foo
{
public DateTime SixtyDaysFromNow()
{
return DateTime.Now + new TimeSpan(60,0,0,0);
}
}
public class CreateInstance1
{
public static void Main(string[] args)
{
try
{
var x = Activator.CreateInstance(null, "Your.Namespace.Foo");
Foo f = (Foo) x.Unwrap();
Console.WriteLine("Result: {0}", f.SixtyDaysFromNow().ToString("G"));
}
catch (System.Exception exc1)
{
Console.WriteLine("Exception: {0}", exc1.ToString());
}
}
}
}
调用Activator.CreateInstance()
指定程序集名称和类名。类名必须是完全限定的(包括所有名称空间)。如果assemblyname为null,则它使用当前运行的程序集。如果要激活的类在当前运行的程序集之外,则需要使用完全限定名称指定程序集。
要从其他程序集加载,您需要使用接受类型的CreateInstance
重载,而不是类型名称;获取给定类型名称的类型的一种方法是使用Type.GetType()
,指定程序集限定名称。
大多数情况下Activator.CreateInstance()
是使用接口类型完成的,因此创建的实例可以强制转换为接口,您可以在接口类型上调用。像这样:
interface ISixty
{
DateTime SixtyDaysFromNow();
}
public class Foo : ISixty
{
public DateTime SixtyDaysFromNow()
{
return DateTime.Now + new TimeSpan(60,0,0,0);
}
}
和
var x = Activator.CreateInstance(null, "Your.Namespace.Foo");
ISixty f = (ISixty) x.Unwrap();
Console.WriteLine("Sixty days from now: {0}", f.SixtyDaysFromNow().ToString("G"));
这样做,您的应用程序(激活应用程序)无需在编译时明确地知道或引用其他程序集。
答案 3 :(得分:3)
警告这个问题的提法。问题是“.NET中的Class.forName()等效?”并且这个问题在这个页面上实际上没有得到解答 - Java中的Class.forName()方法有一个重要的副作用,即.NET等价物没有 - 也就是它实际加载了类。所以如果你有Java的话
Class c = Class.forName("mypackage.PardonMe");
您需要在C#/ .NET中使用两个语句才能获得完整的效果:
Type t = Type.GetType("mypackage.PardonMe");
System.Runtime.CompilerServices.RuntimeHelpers.RunClassConstructor(t.TypeHandle);
这会在不调用任何静态方法或创建任何实例的情况下加载类。