为什么我无法从其他程序集加载类?

时间:2012-06-17 15:42:09

标签: c# reflection .net-assembly

在我的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中。 我给出的代码段是汇编Lib。 班级MembershipRepository位于汇编Repo中。 Web引用了LibRepoLib没有引用任何其他程序集(它可以被称为dll)。 Repo可能会或可能不会引用Lib

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

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

2 个答案:

答案 0 :(得分:2)

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

  

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);

答案 1 :(得分:1)

您正在寻找的是这样的:

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

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