0

アドイン フレームワークとして使用する MAF アドインをテストしています。しかし、私たちは基本的な問題で立ち往生しています。シリアル化可能な型を IContract パラメーターとして使用できますか?

コントラクトとパラメーターの型の両方が同じアセンブリで定義されます。

    public interface IHostContract : IContract
    {
        void SetCurrent(TheValue tagValue);   // does not work
        void SetCurrentSimple(double value);  // works fine
    }

    [Serializable]
    public sealed class TheValue
    {
       public int Id { get; set; }

       public double Value { get; set; }
    }

私たちはすべてを稼働させることができます。SetCurrent を呼び出すと、例外が発生します: AppDomainUnloadedException :

The application domain in which the thread was running has been unloaded.

Server stack trace: 
   at System.Threading.Thread.InternalCrossContextCallback(Context ctx, IntPtr ctxID, Int32 appDomainID, InternalCrossContextDelegate ftnToCall, Object[] args)
   at System.Runtime.Remoting.Channels.CrossAppDomainSink.DoTransitionDispatch(Byte[] reqStmBuff, SmuggledMethodCallMessage smuggledMcm, SmuggledMethodReturnMessage& smuggledMrm)
   at System.Runtime.Remoting.Channels.CrossAppDomainSink.SyncProcessMessage(IMessage reqMsg)

Exception rethrown at [0]: 

プラグインのロードと実行:

public void Run(string PluginFolder)
{
    AddInStore.Rebuild(PluginFolder);
    Collection<AddInToken> tokens = AddInStore.FindAddIns(typeof(Plugins.IPlugin), PluginFolder);

    foreach (var token in tokens)
    {
        Console.WriteLine("Found addin: " + token.Name + " v" + token.Version);
        try
        {
            var plugin = token.Activate<Plugins.IPlugin>(AddInSecurityLevel.FullTrust);
            plugin.PluginHost = this;
            plugin.Start();
            plugin.Stop();
        }
        catch (Exception exception)
        {
            Console.WriteLine("Error starting plugin: " + exception.Message);
        }
    }
}

プラグイン:

[System.AddIn.AddIn("Plugin1", Version = "1.0.0")]
public class Plugin1 : IPlugin
{
    private int started;

    public Plugin1()
    {
        Console.WriteLine("Plugin 1 created");
    }

    public void Start()
    {
        Console.WriteLine("Plugin 1 started: {0}", started);
        started++;

        var tagValue = new TheValue { Id = 1, Value = 4.32 };
        PluginHost.SetCurrent(tagValue);
    }

    public void Stop()
    {
        Console.WriteLine("Plugin 1 stopped");
    }

    public IPluginHost PluginHost { get; set; }
}
4

1 に答える 1

2

ライフタイム管理のガイドラインに従う必要があります。各コントラクトからビューへのアダプターでは、 ContractHandleを格納する必要があります。System.AddInこれは、暗黙的に作成されるプロキシの有効期間管理に必要です (これはSystem.AddIn.NET Remoting に基づいていることに注意してください)。

MSDN から取得:

ContractHandle は、ライフタイム管理にとって重要です。ContractHandle オブジェクトへの参照を維持できなかった場合、ガベージ コレクションによって再利用され、プログラムが予期しないときにパイプラインがシャットダウンされます。これにより、AppDomainUnloadedException など、診断が難しいエラーが発生する可能性があります。シャットダウンは、パイプラインの有効期間における通常の段階であるため、有効期間管理コードがこの状態がエラーであることを検出する方法はありません。

アプリケーションで使用する場合は、 PipelineBuilderSystem.AddInが必要です。ディスカッション ボードでは、VS2010 で動作させる方法についてのヘルプを見つけることができます (非常に簡単です)。VS2012でも動作させるのは難しくないと思います。このツールは、すべての System.AddIn の複雑さを処理します。コントラクトを作成するだけで、残りのパイプラインが作成されます。また、System.AddIn で最も重要なことであるコントラクトの作成方法に関するガイドラインに従うことも確認します。PipelineBuilder

アドイン フレームワークを決定する前に、 MEFを確認することを忘れないでください。AutofacMEFで使用でき、アダプターを介してバージョン管理を提供します。私見、誰もが System.AddIn を選択すべき唯一の理由は、分離機能のためです。ただし、100%の分離は、アドインがホストとは異なるプロセスで読み込まれる場合のみであることに注意してください。

于 2012-11-19T22:30:59.270 に答える