从文本名称实例化一个类

47
不要问我为什么,但我需要执行以下操作:
string ClassName = "SomeClassName";  
object o = MagicallyCreateInstance("SomeClassName");

我想知道有多少种方法可以做到这一点,以及在哪种情况下使用哪种方法。

示例:

  • Activator.CreateInstance
  • Assembly.GetExecutingAssembly.CreateInstance("")
  • 欢迎提出其他建议

此问题不意味着要进行开放式讨论,因为我确信只有这么多种方法可以实现。


可能是 https://dev59.com/NnRB5IYBdhLWcg3wXWK2 的重复问题。 - Amritpal Singh
嗯,你猜得出它的命名空间名称和所属程序集的几率有多大呢? - Hans Passant
程序集所在的类型是否已经加载?如果这是关于插件的事情,你可以看看MEF。 - James Manning
此外,这个类有无参构造函数吗?(具体来说,能否假定它存在) - James Manning
实际上,这些类命名空间是已知的,并且这些类存在于我需要执行此操作的同一程序集中。 - Raheel Khan
3个回答

63

以下是该方法的可能实现:

private static object MagicallyCreateInstance(string className)
{
    var assembly = Assembly.GetExecutingAssembly();

    var type = assembly.GetTypes()
        .First(t => t.Name == className);

    return Activator.CreateInstance(type);
}

上面的代码假设:
  • 您正在查找当前执行程序集中的类(这可以进行调整-只需将 assembly 更改为所需内容)
  • 在该程序集中恰好有一个名称与您要查找的名称相同的类
  • 该类具有默认构造函数
更新:

以下是如何获取从给定类派生并在同一程序集中定义的所有类:

private static IEnumerable<Type> GetDerivedTypesFor(Type baseType)
{
    var assembly = Assembly.GetExecutingAssembly();

    return assembly.GetTypes()
        .Where(baseType.IsAssignableFrom)
        .Where(t => baseType != t);
}

正是我所需要的,谢谢。我还需要枚举所有派生自刚刚创建的这个类的类。我假设 assembly.GetTypes 可以实现这一点。 - Raheel Khan
1
@RaheelKhan 我已经添加了一个代码示例,用于获取在同一程序集中定义的派生类。 - Cristian Lupascu
感谢@w0lf的回复。所以,我们必须先进行强制转换。有没有不需要强制转换的解决方案? - andrefadila
你也可以通过反射调用该方法。(这种方式相当不正规) - Cristian Lupascu
1
或者你可以将对象转换为定义了该方法的接口,而不是其精确类型。 - Cristian Lupascu
显示剩余3条评论

21
Activator.CreateInstance(Type.GetType("SomeNamespace.SomeClassName"));
或者
Activator.CreateInstance(null, "SomeNamespace.SomeClassName").Unwrap();

还有一些重载函数,您可以在其中指定构造函数参数。


0

使用这种方式来使用类名,而无需完全限定的命名空间:

System.Reflection.Assembly.GetExecutingAssembly().CreateInstance("myclass");

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