【问题标题】:Why I can't load classes from other assemblies?为什么我不能从其他程序集中加载类?
【发布时间】:2012-06-18 00:36:08
【问题描述】:

在我的 MVC 项目的 web.config 中,我有这个:

<appSettings>
    <add key="MembershipRepository" value="Repo.MembershipRepository"/>
</appSettings>

我有这样的代码:

var appSettings = ConfigurationManager.AppSettings; 
string membershipRepositoryClassName = appSettings["MembershipRepository"];
Type membershipRepositoryType = Type.GetType(membershipRepositoryClassName);
IMembershipRepository repository = (IMembershipRepository)Activator.CreateInstance(membershipRepositoryType);

假设包含web.config 的Web 应用程序在程序集Web 中。 我给出的代码段在汇编中LibMembershipRepository 类在程序集中 RepoWeb 引用了 LibRepoLib 没有引用任何其他程序集(它可能被引用为 dll)。 Repo 可能引用也可能不引用 Lib

我将membershipRepositoryType 设为null。我知道也许我需要指定 MembershipRepository 所在的程序集。一种方法是在配置中指定程序集名称(如this)。但我认为应该有一些其他的方式。否则如何加载其他类仅从配置文件中获取类名? 例如,MembershipProvider 类可以很好地从其他程序集中加载。

我该怎么做。或者如果我不能,为什么我不能?

【问题讨论】:

  • 疑难解答提示:将true 传递给Type.GetTypeType.GetType(membershipRepositoryClassName, true)—这样您就可以获得描述问题的详细异常。

标签: c# reflection .net-assembly


【解决方案1】:

来自Type.GetType(String) 的 MSDN 库文档:

typeName: 要获取的类型的程序集限定名称。见AssemblyQualifiedName。如果类型在当前执行的程序集中或 Mscorlib.dll 中,则提供由其命名空间限定的类型名称就足够了。

最后一句话解释了为什么当你只指定类名时它有时会起作用:如果执行代码在Repo,那么你可以只指定MembershipProvider。但为了清楚起见(以及性能),我建议您避免这种行为并始终指定程序集名称。或者,如果您已经拥有对包含您的类型的 Assembly 的引用,那么您可以改为调用 Assembly.GetType

但是,如果您确实遇到不知道哪个程序集包含您的类型的情况,那么您可以搜索当前 AppDomain 中所有已加载的程序集并尝试在每个程序集上调用 Assembly.GetType

Type type = AppDomain.CurrentDomain.GetAssemblies()
    .Select(assembly => assembly.GetType(typeName))
    .First(t => t != null);

【讨论】:

  • 谢谢,这解释了一切。我应该在配置中指定程序集。从所有程序集中获取 最可能 类型当然不是一个好主意。我只是想了解为什么我需要在其他人不需要时指定程序集。现在我意识到我以前的一些配置很幸运!!
  • 重新检查配置,如果当前项目中引用了程序集,我似乎不需要指定程序集。是这样吗?
  • 据我所知,不,事实并非如此。例如,即使您的项目可能引用 System.dll,Type.GetType("System.Uri") 将始终返回 null
【解决方案2】:

你正在寻找的是这样的:

var types = AppDomain.CurrentDomain.GetAssemblies().ToList()
    .SelectMany( s => s.GetTypes() )
    .Where( p => p.Name == membershipRepositoryClassName );

这实际上会返回一个列表,因为同名的类型可能会在多个程序集中声明。如果您确定只有一种类型,您可以在链的末尾添加.FirstOrDefault().Single()。如果您不确定该类型是否存在并希望它在不存在时返回 null,请使用 .FirstOrDefault()。如果您确定类型应该存在并且希望它在找不到类型时抛出异常,请使用.Single()

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-05-10
    • 2017-07-09
    • 2019-06-13
    • 1970-01-01
    • 2011-08-05
    • 2011-10-24
    相关资源
    最近更新 更多