MEF,延迟加载高级元数据和序列化异常
MEF, Lazy loading with advanced metadata and serialization exception
我正在开发一个接受插件的应用程序,我决定使用 MEF。一切正常,直到我尝试使用 AppDomain 和 ShadowCopy。现在,在尝试从 MEF 容器中检索插件时,我在元数据接口上遇到序列化异常。
以下是我的代码的几个组成部分:
容器:
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));
}
}
元数据接口:
public interface IPluginMetadata
{
string BackgroundColor { get; }
string BigImageBase64 { get; }
string Description { get; }
string Name { get; }
string PrimaryFontColor { get; }
string SecondaryFontColor { get; }
string SmallImageBase64 { get; }
}
我正在使用的插件:
[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();
}
}
以及使用这两个元素的代码:
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: Type
'proxy_XrmToolBox.Extensibility.Interfaces.IPluginMetadata_bafb7089-c69c-4f81-92f8-a88eda6d70eb'
in assembly 'MetadataViewProxies_760ed609-1713-4fe9-959c-7bfa78012252,
Version=0.0.0.0, Culture=neutral, PublicKeyToken=null' is not marked
as serializable.
XrmToolBox.Extensibility.Interfaces.IPluginMetadata就是上面的高级元数据接口
我不知道 "MetadataViewProxies_760ed609-1713-4fe9-959c-7bfa78012252, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null" 是什么
我该如何解决这个错误?
谢谢
要访问另一个应用程序域中的对象,它们必须是可序列化的。尽管您似乎没有在上面的代码中使用 IPluginMetadata,但我假设它用于强类型的自定义元数据属性。尝试制作可序列化的任何实现。
我正在开发一个接受插件的应用程序,我决定使用 MEF。一切正常,直到我尝试使用 AppDomain 和 ShadowCopy。现在,在尝试从 MEF 容器中检索插件时,我在元数据接口上遇到序列化异常。
以下是我的代码的几个组成部分:
容器:
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));
}
}
元数据接口:
public interface IPluginMetadata
{
string BackgroundColor { get; }
string BigImageBase64 { get; }
string Description { get; }
string Name { get; }
string PrimaryFontColor { get; }
string SecondaryFontColor { get; }
string SmallImageBase64 { get; }
}
我正在使用的插件:
[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();
}
}
以及使用这两个元素的代码:
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: Type 'proxy_XrmToolBox.Extensibility.Interfaces.IPluginMetadata_bafb7089-c69c-4f81-92f8-a88eda6d70eb' in assembly 'MetadataViewProxies_760ed609-1713-4fe9-959c-7bfa78012252, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null' is not marked as serializable.
XrmToolBox.Extensibility.Interfaces.IPluginMetadata就是上面的高级元数据接口
我不知道 "MetadataViewProxies_760ed609-1713-4fe9-959c-7bfa78012252, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null" 是什么
我该如何解决这个错误?
谢谢
要访问另一个应用程序域中的对象,它们必须是可序列化的。尽管您似乎没有在上面的代码中使用 IPluginMetadata,但我假设它用于强类型的自定义元数据属性。尝试制作可序列化的任何实现。