我正在努力将Pages动态加载到现有的Silverlight应用程序中。到现在为止还挺好。从外部.xap工作导入Pages并将数据从主机应用程序导出到插件都正常工作。
主机应用程序使用Web服务,该Web服务公开与后端系统相关的许多类型。我的问题是如何导出Web服务中定义的类型的对象?
示例i导出SMS_SupportedPlatforms的列表,该列表在WS客户端中定义。这是来自托管应用程序。该属性位于Silverlight主应用程序的App.xaml.cs中。它由对Webservice的异步调用填充。
[Export(ExportContracts.SMS_SupportedPlatforms)]
public static List<Client.SMS_SupportedPlatforms> SupportedPlatforms = new List<Client.SMS_SupportedPlatforms>();
编辑: 我已将Imports移动到外部程序集中的Seperate类。他们现在就读到这堂课:
public class NeoServiceManagerImports
{
[Import(NeoSMExportContracts.DepartmentExportAttribute, AllowRecomposition = true)]
public string Department { get; set; }
[Import(NeoSMExportContracts.RolesExportAttribute, AllowRecomposition = true)]
public List<string> Roles { get; set; }
[Import(NeoSMExportContracts.SMS_SupportedPlatforms, AllowRecomposition = true)]
public List<Client.SMS_SupportedPlatforms> SupportedPlatforms
{
get;
set;
}
public NeoServiceManagerImports()
{
CompositionInitializer.SatisfyImports(this);
}
}
此类由要导出的页面的构造函数调用(用于测试目的)。 然后将该页面与MetadataAttribute一起导出到UIProviderbase类中,我用于导出插件(忽略非常抽象的命名;-))该类有一些徽标,标题和页面列表的道具。
[Export(typeof(UIProviderBase))]
public class ExternalMainMenuExternalSubMenuUIProvider: UIProviderBase
{
public override string Title
{
get { return "Submenu"; }
}
public override string ImageUri
{
get { return "uriuri"; }
}
[ImportMany("ExternalSubMenuForExternalMainMenuContract")]
public override List<System.ComponentModel.Composition.ExportFactory<FrameworkElement, IPageMetadata>> EntryPage
{
get;
set;
}
}
我确定该问题与MEF在被两个不同的程序集引用时无法解析类型有关。有没有办法解决这个问题,而无需重构托管应用程序来获取ISMS_SupportedPlatforms列表?目前,托管应用程序似乎正在正确导出,但它从未在插件中被发现。
如果我有AllowDefault = true,则加载页面但SupportedPlatforms保持为null。如果为false,则不会导出页面并以静默方式失败。
我已经改变了我在页面中加载的方式,我正在尝试为您获取更多信息。这是我现在看到的错误
The composition produced a single composition error. The root cause is provided below. Review the CompositionException.Errors property for more detailed information.
1) No valid exports were found that match the constraint '((exportDefinition.ContractName == "SMS_SupportPlatformsExport") AndAlso (exportDefinition.Metadata.ContainsKey("ExportTypeIdentity") AndAlso "System.Collections.Generic.List(HelloWorld.MEF.Client.SMS_SupportedPlatforms)".Equals(exportDefinition.Metadata.get_Item("ExportTypeIdentity"))))', invalid exports may have been rejected.
Resulting in: Cannot set import 'HelloWorld.MEF.NeoServiceManagerImports.SupportedPlatforms (ContractName="SMS_SupportPlatformsExport")' on part 'HelloWorld.MEF.NeoServiceManagerImports'.
Element: HelloWorld.MEF.NeoServiceManagerImports.SupportedPlatforms (ContractName="SMS_SupportPlatformsExport") --> HelloWorld.MEF.NeoServiceManagerImports
Resulting in: An exception occurred while trying to create an instance of type 'HelloWorld.MEF.ExternalMainMenuExternalSubMenu'.
Resulting in: Cannot activate part 'HelloWorld.MEF.ExternalMainMenuExternalSubMenu'.
Element: HelloWorld.MEF.ExternalMainMenuExternalSubMenu --> HelloWorld.MEF.ExternalMainMenuExternalSubMenu --> AssemblyCatalog (Assembly="HelloWorld.MEF, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null")
Resulting in: Cannot get export 'HelloWorld.MEF.ExternalMainMenuExternalSubMenu (ContractName="ExternalSubMenuForExternalMainMenuContract")' from part 'HelloWorld.MEF.ExternalMainMenuExternalSubMenu'.
Element: HelloWorld.MEF.ExternalMainMenuExternalSubMenu (ContractName="ExternalSubMenuForExternalMainMenuContract") --> HelloWorld.MEF.ExternalMainMenuExternalSubMenu --> AssemblyCatalog (Assembly="HelloWorld.MEF, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null")
这是出现异常的代码
var page = (from p in this.Plugins
from e in p.EntryPage
where e.Metadata.NavigateUri == this.targetUri.ToString()
select e).Single().CreateExport().Value;
驻留在此课程中(动态加载页面)
public class MefContentLoader : INavigationContentLoader
{
private PageResourceContentLoader pageResourceContentLoader = new PageResourceContentLoader();
private Uri targetUri;
[ImportMany(AllowRecomposition = true)]
public UIProviderBase[] Plugins
{
get;
set;
}
public MefContentLoader()
{
CompositionInitializer.SatisfyImports(this);
}
#region INavigationContentLoader Members
public IAsyncResult BeginLoad(Uri targetUri, Uri currentUri, AsyncCallback userCallback, object asyncState)
{
this.targetUri = targetUri;
return pageResourceContentLoader.BeginLoad(targetUri, currentUri, userCallback, asyncState);
}
public bool CanLoad(Uri targetUri, Uri currentUri)
{
// TODO: Handle this properly
return true;
}
public void CancelLoad(IAsyncResult asyncResult)
{
// TODO: Handle this properly
pageResourceContentLoader.CancelLoad(asyncResult);
}
public LoadResult EndLoad(IAsyncResult asyncResult)
{
if (this.Plugins.Length == 0 ||
this.Plugins.Count(p => p.EntryPage != null && p.EntryPage.Any(u => u.Metadata.NavigateUri == targetUri.ToString())) == 0)
{
return pageResourceContentLoader.EndLoad(asyncResult);
}
var page = (from p in this.Plugins
from e in p.EntryPage
where e.Metadata.NavigateUri == this.targetUri.ToString()
select e).Single().CreateExport().Value;
return new LoadResult(page);
}
#endregion
}
总结一下: 在程序集B(插件)中,我将大量页面导出到程序集B中的UIProviderbase。页面需要使用程序集A(主要Silverlight应用程序)中的数据。然后,程序集A需要将UIProviderbase作为插件导入,并从中获取一组菜单页面,将它们添加到应用程序中。 这适用于除Web服务中定义的类型之外的所有类型,即程序集A和B都有引用。
答案 0 :(得分:1)
事实证明,它是某种形式的类型匹配或类型不兼容。在插件(程序集B)中,我添加了对程序集A的引用并使用了那里的类型:
[Import(AllowRecomposition = true)]
public Lazy<List<NeoServiceManager.Client.SMS_SupportedPlatforms>> SupportedPlatforms
{
get;
set;
}
我没有用ContractName装饰导出或导入,因为在这种情况下不需要它,并且类型是明确的。
答案 1 :(得分:0)
您的List属性在哪里?
尝试使用:
Container.GetExportedValues<Client.SMS_SupportedPlatforms>()