简体   繁体   English

合同中可序列化类型的MAF(System.Addin)属性?

[英]MAF (System.Addin) property of serializable type in contract?

We are testing the MAF addin to use as our addin framework. 我们正在测试MAF插件以用作我们的插件框架。 But we get stuck at a basic issue. 但是我们陷入了一个基本问题。 Can we use serializable types as IContract parameters? 我们可以使用可序列化类型作为IContract参数吗?

Both the contract and the parameter type is defined in the same assembly: 合同和参数类型都在同一个程序集中定义:

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

We are able to get everything up and running. 我们能够让一切运转起来。 Calling the SetCurrent results in an exception: AppDomainUnloadedException : 调用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]: 

Loading and running of plugins: 加载和运行插件:

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);
        }
    }
}

Plugin: 插入:

[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; }
}

You need to follow the guidelines for lifetime management . 您需要遵循终身管理准则。 In each contract-to-view adapter you need to store a ContractHandle . 在每个合同到视图适配器中,您需要存储ContractHandle This is necessary for the lifetime management of the proxies that System.AddIn implicitly creates (remember that System.AddIn is based on .NET Remoting). 这对于System.AddIn隐式创建的代理的生命周期管理是必需的(请记住, System.AddIn基于.NET Remoting)。

Taken from MSDN: 摘自MSDN:

The ContractHandle is critical to lifetime management. ContractHandle对于终身管理至关重要。 If you fail to keep a reference to the ContractHandle object, garbage collection will reclaim it, and the pipeline will shut down when your program does not expect it. 如果您未能保留对ContractHandle对象的引用,则垃圾回收将回收它,并且当您的程序不期望它时管道将关闭。 This can lead to errors that are difficult to diagnose, such as AppDomainUnloadedException. 这可能导致难以诊断的错误,例如AppDomainUnloadedException。 Shutdown is a normal stage in the life of a pipeline, so there is no way for the lifetime management code to detect that this condition is an error. 关闭是管道生命周期中的正常阶段,因此生命周期管理代码无法检测到此条件是错误。

If you decide to use System.AddIn in your application then you need the PipelineBuilder . 如果您决定在应用程序中使用System.AddIn ,那么您需要PipelineBuilder In the discussion board you will find help on how to make it work with VS2010 (it is quite simple). 在讨论板中,您将找到有关如何使其与VS2010一起使用的帮助(这非常简单)。 I guess it will not be hard to make it work with VS2012 as well. 我想也不难让它与VS2012一起工作。 This tool will take care all the System.AddIn intricacies for you. 此工具将为您处理所有System.AddIn复杂性。 All you will need to do is create the contracts and PipelineBuilder will create the rest of the pipeline for you. 您需要做的就是创建合同, PipelineBuilder将为您创建剩余的管道。 It will also make sure that you follow the guidelines on how to build your contracts which is the most important thing with System.AddIn. 它还将确保您遵循有关如何构建合同的指导,这是System.AddIn最重要的事情。

Before you decide on an add-in framework, don't forget to check out MEF . 在决定加载项框架之前,不要忘记查看MEF MEF can be used with Autofac and provide versioning through adapters. MEF可与Autofac一起使用,并通过适配器提供版本控制。 IMHO, the only reason that anyone should choose System.AddIn is for the isolation feature. 恕我直言,任何人都应该选择System.AddIn的唯一原因是隔离功能。 But note that 100% isolation is only when the add-ins are loaded in a different process from the host. 但请注意,仅当加载项在与主机不同的进程中加载​​时才会实现100% 隔离

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM