加载程序集时发生冲突的依赖项

本文关键字:依赖 冲突 程序集 加载 | 更新日期: 2023-09-27 18:15:08

我在尝试编写插件处理程序时遇到了一些问题。

我有一个主应用程序"AppA",引用"AssemblyX"。

AppA还加载了一些实现"IPlugin"接口的插件程序集。然而,这些插件也可能引用"AssemblyX",它甚至可能是一个旧版本。

所以最初的问题是在通过Assembly.LoadFrom()加载插件时与AssemblyX发生冲突。

在这里进行了一些研究之后,我尝试在一个新的AppDomain中加载插件。这本身并不能解决问题。接下来,我创建了一个继承自MarshalByRefObject的ProxyDomain类。还是没有快乐。

最后,我让插件本身继承了MarshalByRefObject,这确实产生了更多的成功,但是当我试图将List绑定到ListView时,它抱怨"System. conf"。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可能包含多个插件类。

加载程序集时发生冲突的依赖项

如果我理解正确,您可以在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个单独的条目。