2010-12-02 24 views
2

Ich arbeite daran, das dynamische Laden von Pages in eine vorhandene Silverlight-Anwendung zu implementieren. So weit, ist es gut. Sowohl das Importieren von Seiten aus der externen .xap-Datei als auch das Exportieren von Daten aus der Host-Anwendung in die Plugins funktioniert.Exportieren/Importieren externer Typen in MEF - Silverlight

Die Host-Anwendung verbraucht einen Webservice, der eine Reihe von Typen für das Backend-System verfügbar macht. Meine Frage ist, wie exportiert ich Objekte von Typen, die im Webservice definiert sind?

Ein Beispiel i Exportieren Sie eine Liste der SMS_SupportedPlatforms, die im WS-Client definiert ist. Dies ist von der Hosting-Anwendung. Die Eigenschaft befindet sich in der App.xaml.cs der Silverlight-Hauptanwendung. Es wird durch einen asynchronen Aufruf an den Webservice gefüllt.

[Export(ExportContracts.SMS_SupportedPlatforms)] 
    public static List<Client.SMS_SupportedPlatforms> SupportedPlatforms = new List<Client.SMS_SupportedPlatforms>(); 

Edited: ich die Importe auf eine Seperate-Klasse in den externen Baugruppen verschoben haben. Sie recide jetzt in dieser Klasse:

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); 
     } 

}

Diese Klasse durch den Konstruktor der Seite genannt (zu Testzwecken) exportiert werden. Die Seite wird dann mit einem MetadataAttribute in eine UIProviderbase-Klasse exportiert, die ich zum Exportieren von Plugins verwendet habe (ignoriere die sehr abstrakte Benennung ;-)) Die Klasse hat ein paar Requisiten für ein Logo, einen Titel und eine Seitenliste.

[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; 
     } 
    } 

ich sicher, dass das Problem betrifft die Art, wie das gleiche zu lösen nicht in der Lage MEF, wenn sie von zwei verschiedenen Baugruppen verwiesen wird. Gibt es eine Möglichkeit, dies zu lösen, ohne die Hosting-Anwendung zu refactorieren, um eine Liste von ISMS_SupportedPlatforms zu erstellen? Momentan scheint es so zu sein, dass die Hosting-Anwendung korrekt exportiert, aber im Plugin nie gefunden wird.

Wenn ich AllowDefault = true habe, wird die Seite geladen, aber SupportedPlatforms bleibt null. Wenn der Wert false ist, wird die Seite nicht exportiert und es tritt kein Fehler auf.

Ich habe die Art und Weise geändert, wie ich die Seiten ein bisschen lade, und ich versuche, weitere Informationen für Sie zu bekommen. Dies ist der Fehler, den ich jetzt sehen

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") 

Dies ist der Code, wo die Ausnahme

var page = (from p in this.Plugins 
        from e in p.EntryPage 
        where e.Metadata.NavigateUri == this.targetUri.ToString() 
        select e).Single().CreateExport().Value; 

Residieren in dieser Klasse erscheint (die Seiten dynamisch Laden)

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 


    } 

Zusammengefasst : In Assembly B (Plugin) exportiere ich eine Anzahl von Seiten in eine UIProviderbase in Assembly B. Die Seiten müssen Daten von Assembly konsumieren A (Haupt Silverlight App). Assembly A muss dann die UIProviderbase als Plugins importieren und von diesen eine Sammlung von Menüseiten erhalten, die sie der Anwendung hinzufügen. Dies funktioniert mit allen außer den im Webservice definierten Typen, auf die sowohl Baugruppe A als auch B Bezug haben.

+0

Was ist das Verhalten, das Sie tatsächlich sehen? Es gibt nicht wirklich genug Informationen, um zu sagen, was falsch ist, aber ich bezweifle, dass das Problem damit zu tun hat, dass der Typ nicht passt. –

+0

Hallo Daniel. Wenn ich AllowDefault = true habe, wird die Seite gerendert, aber SupportedPlatforms ist null. Wenn nicht, wird die Seite überhaupt nicht als Export markiert. – anders

+0

Daniel, wenn du Lust hast, das nochmal anzusehen. Ich habe einige weitere Informationen hinzugefügt :) – anders

Antwort

1

Es stellte sich heraus, es irgendeine Form von jedem Typ passende oder Typ incompatability war. Im Plugin (Assembly B), fügte ich einen Verweis auf Assembly A und verwendet, um die Art von dort:

[Import(AllowRecomposition = true)] 
public Lazy<List<NeoServiceManager.Client.SMS_SupportedPlatforms>> SupportedPlatforms 
{ 
    get; 
    set; 
} 

ich nicht den Export oder Import mit einem ContractName eingerichtet haben, da es in diesem Fall nicht benötigt wird und die Typ ist eindeutig.

0

Wo lebt Ihre List-Eigenschaft?

Versuchen zu verwenden:

Container.GetExportedValues<Client.SMS_SupportedPlatforms>() 
+0

Ich habe den ursprünglichen Beitrag aktualisiert. Sollte ich mehr Code posten? – anders

+0

Es scheint zu exportieren: http://yfrog.com/nfsampleyp – anders