首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >MEF,延迟加载高级元数据和序列化异常

MEF,延迟加载高级元数据和序列化异常
EN

Stack Overflow用户
提问于 2015-10-07 12:30:31
回答 1查看 820关注 0票数 3

我正在开发一个接受插件的应用程序,我决定使用MEF。在我尝试使用AppDomain和ShadowCopy之前,一切都很好。现在,当试图从MEF容器中检索插件时,我面临的是元数据接口上的序列化异常。

下面是我的代码的几个组件:

容器:

代码语言:javascript
复制
public class PluginManagerExtended : MarshalByRefObject
    {
        private static readonly string PluginPath = Path.Combine(AppDomain.CurrentDomain.SetupInformation.ApplicationBase, "Plugins");
        private CompositionContainer container;
        private DirectoryCatalog directoryCatalog;            

        [ImportMany(AllowRecomposition = true)]
        public IEnumerable<Lazy<IXrmToolBoxPlugin, IPluginMetadata>> Plugins { get; set; }

        public void Initialize()
        {
            try
            {
                var regBuilder = new RegistrationBuilder();
                regBuilder.ForTypesDerivedFrom<Lazy<IXrmToolBoxPlugin, IPluginMetadata>>().Export<Lazy<IXrmToolBoxPlugin, IPluginMetadata>>();

                var catalog = new AggregateCatalog();
                catalog.Catalogs.Add(new AssemblyCatalog(typeof(PluginManagerExtended).Assembly, regBuilder));

                directoryCatalog = new DirectoryCatalog(PluginPath, regBuilder);
                catalog.Catalogs.Add(directoryCatalog);

                container = new CompositionContainer(catalog);
                container.ComposeParts(this);
            }
            catch (ReflectionTypeLoadException ex)
            {
                if (ex.LoaderExceptions.Length == 1)
                {
                    throw ex.LoaderExceptions[0];
                }
                var sb = new StringBuilder();
                var i = 1;
                sb.AppendLine("Multiple Exception Occured Attempting to Intialize the Plugin Manager");
                foreach (var exception in ex.LoaderExceptions)
                {
                    sb.AppendLine("Exception " + i++);
                    sb.AppendLine(exception.ToString());
                    sb.AppendLine();
                    sb.AppendLine();
                }

                throw new ReflectionTypeLoadException(ex.Types, ex.LoaderExceptions, sb.ToString());
            }
        }

        public void Recompose()
        {
            directoryCatalog.Refresh();
            container.ComposeParts(directoryCatalog.Parts)
        }

        internal void DoSomething()
        {
            Plugins.ToList().ForEach(p => MessageBox.Show(p.Metadata.Name));
        }
}

元数据接口:

代码语言:javascript
复制
public interface IPluginMetadata
{
    string BackgroundColor { get; }
    string BigImageBase64 { get; }
    string Description { get; }
    string Name { get; }
    string PrimaryFontColor { get; }
    string SecondaryFontColor { get; }
    string SmallImageBase64 { get; }
}

,我正在使用的插件:

代码语言:javascript
复制
[Export(typeof(IXrmToolBoxPlugin)),
ExportMetadata("Name", "A Sample Tool 2"),
ExportMetadata("Description", "This is a tool to learn XrmToolBox developement")
ExportMetadata("SmallImageBase64", null),
ExportMetadata("BigImageBase64", null),
ExportMetadata("BackgroundColor", "Lavender"),
ExportMetadata("PrimaryFontColor", "#000000"),
ExportMetadata("SecondaryFontColor", "DarkGray")]
public class Plugin : PluginBase
{
    /// <summary>
    /// This method return the actual usercontrol that will
    /// be used in XrmToolBox
    /// </summary>
    /// <returns>User control to display</returns>
    public override IXrmToolBoxPluginControl GetControl()
    {
        return new SampleTool2();
    }
}

和使用这两种元素的代码:

代码语言:javascript
复制
var cachePath = Path.Combine(AppDomain.CurrentDomain.SetupInformation.ApplicationBase,
    "ShadowCopyCache");
var pluginsPath = Path.Combine(AppDomain.CurrentDomain.SetupInformation.ApplicationBase,
    "Plugins");

if (!Directory.Exists(cachePath))
{
    Directory.CreateDirectory(cachePath);
}
if (!Directory.Exists(pluginsPath))
{
    Directory.CreateDirectory(pluginsPath);
}

var setup = new AppDomainSetup
{
    CachePath = cachePath,
    ShadowCopyFiles = "true",
    ShadowCopyDirectories = pluginsPath
};

domain = AppDomain.CreateDomain("XrmToolBox_AppDomain", AppDomain.CurrentDomain.Evidence, setup);
pManager =
    (PluginManagerExtended)
        domain.CreateInstanceAndUnwrap(typeof(PluginManagerExtended).Assembly.FullName,
            typeof(PluginManagerExtended).FullName);

pManager.Initialize();

// This code works well as the Metadata are accessed in the container
pManager.DoSomething();

// This code fails
string plugins = String.Join(",", pManager.Plugins.Select(p => p.Metadata.Name));

我得到的例外是:

程序集中的System.Runtime.Serialization.SerializationException:类型'proxy_XrmToolBox.Extensibility.Interfaces.IPluginMetadata_bafb7089-c69c-4f81-92f8-a88eda6d70eb‘( 'MetadataViewProxies_760ed609-1713-4fe9-959c-7bfa78012252,Version=0.0.0.0、Culture=neutral、PublicKeyToken=null’)未标记为可序列化。

XrmToolBox.Extensibility.Interfaces.IPluginMetadata是上面的高级元数据接口。

我不知道"MetadataViewProxies_760ed609-1713-4fe9-959c-7bfa78012252,Version=0.0.0.0,Culture=neutral,PublicKeyToken=null是什么

我能做些什么来纠正这个错误?

谢谢

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2015-10-07 13:15:41

若要访问另一个app域中的对象,它们必须是可序列化的。虽然您似乎没有在上面的代码中使用IPluginMetadata,但我假设它用于强类型定制元数据属性。试着做任何可序列化的工具。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/32992277

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档