[英]Exporting / Importing external types in MEF - Silverlight
我正在努力將Pages動態加載到現有的Silverlight應用程序中。 到現在為止還挺好。 從外部.xap的工作導入Pages和從主機應用程序向插件導出數據都在工作。
主機應用程序使用Web服務,該服務公開了許多與后端系統有關的類型。 我的問題是如何導出Web服務中定義的類型的對象?
一個示例i導出在WS客戶端中定義的SMS_SupportedPlatforms列表。 這是來自托管應用程序。 該屬性位於主Silverlight應用程序的App.xaml.cs中。 它是通過對Web服務的異步調用來填充的。
[Export(ExportContracts.SMS_SupportedPlatforms)]
public static List<Client.SMS_SupportedPlatforms> SupportedPlatforms = new List<Client.SMS_SupportedPlatforms>();
編輯:我已將導入移動到外部程序集中的一個單獨的類。 他們現在參加這個班級:
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);
}
}
要導出的Page的構造方法調用的此類(出於測試目的)。 然后將頁面與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保持為空。 如果為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(Main Silverlight應用程序)中的數據。 然后,程序集A需要將UIProviderbase作為插件導入,並從中獲得菜單頁面的集合,將其添加到應用程序中。 這適用於Web服務中定義的類型以外的所有類型,而程序集A和B均引用了該類型。
事實證明,這是某種類型的匹配或類型不兼容的形式。 在插件(程序集B)中,我添加了對程序集A的引用,並從那里使用了類型:
[Import(AllowRecomposition = true)]
public Lazy<List<NeoServiceManager.Client.SMS_SupportedPlatforms>> SupportedPlatforms
{
get;
set;
}
我沒有用ContractName裝飾導出或導入,因為在這種情況下不需要使用它,並且類型是明確的。
您的List財產住在哪里?
嘗試使用:
Container.GetExportedValues<Client.SMS_SupportedPlatforms>()
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.