【问题标题】:How can I get a type from a referenced assembly via reflection如何通过反射从引用的程序集中获取类型
【发布时间】:2010-02-18 18:26:23
【问题描述】:

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

如何编写可以找到这种类型的代码?如果我执行以下操作

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

    // Instantiate the type...
}

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

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

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

【问题讨论】:

  • typeName 的值是多少?它是完全限定名称吗?

标签: c# reflection


【解决方案1】:

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

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

虽然它可能不是最高效的。再说一次,您正在使用反射。

【讨论】:

  • 好主意。它对我来说不太适用,因为程序集不是直接引用的,而是由调用程序集间接引用的;大概我可以通过在每个找到的程序集上递归调用 .GetReferencedAssembly() 来找到它(并从 .GetEntryAssembly() 而不是 .GetExecutingAssembly() 开始)。是的,它的性能不是很好,但这对我来说没关系,因为它是启动代码并且只运行一次。
【解决方案2】:

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

您可以做的是通过使用typeof 表达式强制程序集进入进程。例如

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

【讨论】:

  • 谢谢,这似乎可行 - 因为所有可能的类型都在同一个程序集中,所以我只需要为一种类型做。不过感觉很丑。
【解决方案3】:

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

【讨论】:

    猜你喜欢
    • 2023-04-04
    • 2010-12-26
    • 2013-03-09
    • 1970-01-01
    • 2017-04-14
    • 1970-01-01
    • 2013-04-02
    • 1970-01-01
    相关资源
    最近更新 更多