簡體   English   中英

在MEF中導出/導入外部類型-Silverlight

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM