只知道类名创建一个对象?

我有一组课程,每一个课程都是做同样工作的不同策略 。

namespace BigCorp.SuperApp { public class BaseClass { } public class ClassA : BaseClass { } public class ClassB : BaseClass { } } 

选择使用哪种策略是可配置的。 我想在app.config文件中只配置类名“ClassB”而不是完整类型名称“BigCorp.SuperApp.ClassB”。

      

但是,reflection调用失败,因为它们期望完整的类型名称,尤其是

 Type t = Type.GetType("ClassB"); // results in t == null BaseClass c = Activator.CreateInstance(t) as BaseClass; // fails 

如何在仅配置类名时才能使其工作? 将名称空间连接到完整类型名称的类名? 是否有其他reflection调用有效?

如果你认为这是无用的,我希望配置包含完整的类型名称,我对这个解决方案持开放态度! 只是提供说服我的理由。

(我不会从此程序集/命名空间外部加载类型)

既然您知道所有类都来自同一个命名空间,请配置一次并使用它:

      

编辑:我将名称更改为以更好地表示该属性的含义。

使用assembly-qualified-name,或获取Assembly并使用Assembly.GetType(name) 。 在这种情况下,由于您需要配置文件中的类型,因此assembly-qualified是一种有效的方法 – 但是因为您知道所有类型都在同一个程序集中:

 Assembly assembly = typeof(SomeKnownType).Assembly; // in the same assembly! Type type = assembly.GetType(name); // full name - ie with namespace (perhaps concatenate) object obj = Activator.CreateInstance(type); 

静态Type.GetType(string)具有经常引起混淆的探测规则……它查看调用程序集和一些系统程序集 – 但不是所有已加载的程序集。

  (我不会从此程序集/命名空间外部加载类型) 

由于上面这一行,可以安全地假设您知道命名空间是什么。 你做不到这样的事情:

 Type t = Type.GetType("Namespace." + className); BaseClass c = Activator.CreateInstance(t) as BaseClass; 

如果您希望将来可能能够添加其他策略类(可能通过其他程序集),则需要完全限定类名。 无论如何,这是建议的,因为您可以为您的应用程序提供增强的可扩展性。

我将在应用程序配置中使用完整类型名称。 下面是一个稍微完整但仍然无足轻重的例子

       

实际创造这个的工厂类

 private static Assembly a = typeof(IFactoryObject).Assembly; public static IFactoryObject CreateObject(String providerName) { Type t = a.GetType(providerName) IFactoryObject o = Activator.CreateInstance(t) as IFactoryObject; return o; } 
 BaseClass c = Activator.CreateInstance(t) as BaseClass; // fails 

也可能是因为CreateInstance没有返回BaseClass的实例,而是返回包装到ObjectHandle中的BaseClass实例。

使用UnWrap方法后,将其强制转换为BaseClass。