加载程序集时发生冲突的依赖项
Posted
技术标签:
【中文标题】加载程序集时发生冲突的依赖项【英文标题】:Conflicting dependencies when loading an assembly 【发布时间】:2014-07-25 18:39:02 【问题描述】:我在尝试编写插件处理程序时遇到了一些问题。
我有一个主应用程序“AppA”,它引用了“AssemblyX”。
AppA 还加载了许多实现“IPlugin”接口的插件程序集。但是,这些插件也可能引用“AssemblyX”,甚至可能是旧版本。
所以最初的问题是通过 Assembly.LoadFrom() 加载插件时与 AssemblyX 发生冲突。
在这里进行了一些研究后,我尝试将插件加载到新的 AppDomain 中。这本身并没有解决问题。接下来我创建了一个继承自 MarshalByRefObject 的 ProxyDomain 类。仍然没有喜悦。
最后我让插件本身继承自 MarshalByRefObject,这确实取得了更大的成功,但是当我尝试将 List 绑定到 ListView 时,它抱怨“System.MarshalByRefObject'不包含名为'SomeProperty'的属性” .
请有人看一下我的代码,看看是否可以进行任何更改:
public partial class WebForm1 : System.Web.UI.Page
protected void Button1_Click(object sender, EventArgs e)
AssemblyX x = new AssemblyX();
x.GetStuff("a", "b");
lstConfig.DataSource = PluginLoader.Load(Path.Combine(PluginLoader.GetPluginFolderPath(), "ExamplePlugins.dll"));
lstConfig.DataBind();
public class PluginLoader
public static List<IPlugin> Load(string file)
var plugins = new List<IPlugin>();
ProxyDomain pd = new ProxyDomain();
Assembly ass = pd.GetAssembly(file);
try
AppDomainSetup adSetup = new AppDomainSetup();
string fileName = Path.GetFileName(file);
string path = file.Replace(fileName, "");
adSetup.ApplicationBase = path;
AppDomain crmAppDomain = AppDomain.CreateDomain("ProxyDomain", null, adSetup);
foreach (Type t in ass.GetTypes())
Type hasInterface = t.GetInterface(typeof(IPlugin).FullName, true);
if (hasInterface != null && !t.IsInterface)
IPlugin plugin = (IPlugin)crmAppDomain.CreateInstanceAndUnwrap(ass.FullName, t.FullName);
plugins.Add(plugin);
catch (Exception ex)
return plugins;
public class ProxyDomain : MarshalByRefObject
public Assembly GetAssembly(string assemblyPath)
try
return Assembly.LoadFrom(assemblyPath);
catch (Exception ex)
throw ex;
public interface IPlugin
string SomeProperty get; set;
void DoSomething();
[Serializable]
public class ExamplePlugin : MarshalByRefObject, IPlugin
public string SomeValue
get
AssemblyX x = new AssemblyX(); // Referencing a previouus version of AssemblyX
return x.GetStuff("c");
set
public void DoSomething()
注意:PluginExamples.dll 可能包含多个插件类。
【问题讨论】:
你试试 System.Addins 命名空间的东西吗? MAF 可以解决许多关于版本控制的问题(如果它们不能简单地使用适当的清单文件解决)... 【参考方案1】:如果我理解正确,您可以在 app.config 中像这样指定 AssemblyX 的特定版本:
<configuration>
<runtime>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
<assemblyIdentity name="AssemblyX" publicKeyToken="3d67ed1f87d44c89" />
<codeBase version="3.0" href=".\ver30\AssemblyX.dll"/>
<codeBase version="5.0" href=".\ver50\AssemblyX.dll"/>
</dependentAssembly>
</assemblyBinding>
</runtime>
</configuration>
如果版本的公钥令牌不同,则必须指定 2 个单独的条目。
【讨论】:
嗨,我不想重定向,因为版本可能不兼容。例如,应用程序需要使用第 5 版的 AssemblyX,但插件可能只使用第 2 版的 AssemblyX。 这不是重定向,而是告诉框架如何绑定不同版本的程序集。上面的示例正是解决您遇到的问题的方法。以上是关于加载程序集时发生冲突的依赖项的主要内容,如果未能解决你的问题,请参考以下文章
加载依赖于另一个域的程序集时的 FileNotFound [重复]
无法加载文件或程序集或其依赖项之一。访问被拒绝。问题是随机的,但发生一次后,它会继续