0

プラグイン ハンドラを作成しようとすると、いくつかの問題が発生します。

「AssemblyX」を参照するメインアプリケーション「AppA」があります。

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 には、複数のプラグイン クラスが含まれている場合があります。

4

1 に答える 1

0

あなたが正しいことを理解していれば、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 つの別個のエントリを指定する必要があります。

于 2014-07-25T19:20:59.673 に答える