2010-02-18 25 views
5

假设我有一个工厂方法,它想要构建在运行时通过反射选择的类型的实例。进一步假设我的工厂方法是通用代码,它不直接引用包含指定类型的程序集,尽管它将从具有必要程序集引用的应用程序中运行。如何通过反射从引用的程序集中获取类型

我该如何着手编写可以找到这种类型的代码?如果我做了以下

public object CreateInstance(string typeName) 
{ 
    Type desiredType = Assembly.GetExecutingAssembly().GetType(typename); 

    // Instantiate the type... 
} 

这似乎失败,因为该类型未在执行的程序集定义。如果我可以在运行时获得所有可用的程序集,我可以遍历它们并找出哪一个包含我想要的类型。但我看不出有办法做到这一点。 AppDomain.CurrentDomain.GetAssemblies()看起来很有前途,但不会返回我在项目中引用的所有程序集。

编辑:有几个人指出我需要加载程序集。麻烦的是,这段代码不知道应该加载哪个程序集,因为我试图以不依赖于其他程序集的方式编写代码。

我故意省略typeName的细节,因为从字符串到类型的映射实际上在我的真实代码中更加复杂。实际上,类型是由包含指定字符串的自定义属性标识的,但是如果我可以获取类型列表,那么将列表限制为所需类型时不存在问题。

+0

typeName中的值是什么?这是完全合格的名字吗? – 2010-02-18 18:50:02

回答

9

AppDomain.CurrentDomain.GetAssemblies()的调用仅返回当前加载到AppDomain中的一组DLL。根据需要将DLL加载到CLR进程中;因此在实际使用之前,它不会包含项目中引用的所有DLL。

你可以做什么,是通过使用typeof表达式强制程序集进入过程。例如

var force1 = typeof(SomeTypeInTheProject).Assembly; 
var force2 = typeof(SomeTypeInProject2).Assembly; 
+0

谢谢,这似乎工作 - 因为所有可能的类型都在同一个程序集中,我只需要为一种类型。不过,这感觉相当难看。 – 2010-02-18 19:05:39

2

AppDomain.CurrentDomain.GetAssemblies()只返回加载的程序集。所以你需要加载引用程序集,如果它尚未加载。

10

您可以使用GetReferencedAssemblies并遍历所有类型,直到找到所需的类型。

var t = Assembly 
    .GetExecutingAssembly() 
    .GetReferencedAssemblies() 
    .Select(x => Assembly.Load(x)) 
    .SelectMany(x => x.GetTypes()).First(x => x.FullName == typeName); 

虽然它可能不是最高性能的。然后再次,你使用反射。

+0

好主意。它不适合我,因为程序集不是直接引用的,而是被调用程序集间接引用;大概我能找到它递归调用.GetReferencedAssemblies()在每个找到的程序集(并从.GetEntryAssembly(),而不是.GetExecutingAssembly())。是的,这对性能并不是很好,但对我来说这没问题,因为它是启动代码,只能运行一次。 – 2010-02-18 20:57:14

相关问题