2012-11-19 23 views
0

我們正在測試MAF插件用作我們的插件框架。但是我們陷入了一個基本問題。我們可以使用可序列化的類型作爲IContract參數嗎?MAF(System.Addin)屬性中的可序列化類型?

無論是合同,參數類型是在同一程序中定義:

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; } 
} 
+0

您應仔細閱讀由負責System.AddIn http://blogs.msdn.com/b/clraddins/archive/2007/02/27/restrictions-on-contracts團隊中的一員以下博客條目。 aspx TheValue應該是合約程序集中的一個結構體。順便說一句我已經使用System.AddIn廣泛的幾年,我不會推薦它除了主機暴露在加載項(如Visual Studio,微軟Office等)。如果你想創建一個更復雜的設計,使用配合或樂高設計的插件,那麼MEF或Mono.AddIns是更好的選擇。 –

+0

您可以通過添加加載代碼並初始化加載項來更新您的問題嗎? –

+0

使用MAF的原因是因爲我們認爲我們需要隔離appdomains。我們必須同時支持同一插件的新舊版本的運行。我們也會看看Mono Addins。更新了問題中的代碼以包含加載。 – Julius

回答

2

你需要遵循的準則爲lifetime management。在每個合同到視圖的適配器中,您需要存儲ContractHandle。這是必要的是System.AddIn暗中創建的代理的生命週期管理(記住,System.AddIn基於.NET Remoting的)。

從MSDN摘自:

的ContractHandle是生命週期管理的關鍵。如果你沒有 保持到ContractHandle對象的引用,垃圾回收 回收它,該管道將關閉時,你的程序不 指望它。這可能會導致難以診斷的錯誤,例如AppDomainUnloadedException。關機是在 人生管道的正常階段,所以沒有辦法,生命週期管理 代碼來檢測這種情況是一個錯誤。

如果你決定在你的應用程序中使用System.AddIn,那麼你需要的PipelineBuilder。在討論板中,您將找到關於如何使其與VS2010協同工作的幫助(這非常簡單)。我想這與VS2012一起工作也不會很難。該工具將爲您處理所有System.AddIn錯綜複雜的問題。您需要做的就是創建合同,PipelineBuilder將爲您創建管道的其餘部分。它還將確保您遵循有關如何構建與System.AddIn最重要的合同的指導原則。

你決定一個外接的框架之前,不要忘記檢查MEFMEF可以與Autofac一起使用,並通過適配器提供版本控制。恕我直言,任何人都應該選擇System.AddIn的唯一原因是隔離功能。但請注意,只有當加載項在與主機不同的進程中加載​​時,100%isolation纔是。

+0

謝謝!就是這樣。我不認爲我們可以避免appdomains的隔離。我們將有一個窗口,服務需要連續運行,加載和卸載插件。 – Julius

相關問題