19 thoughts on “MEF Teil 2 – Metadaten und Erstellungsrichtlinien”

  1. Hi Stefan,

    Ich bin auch ein Freund von MEF.
    Super Artikel! Bin schon auf den nächsten Teil gespannt.
    Nur eine Kleinigkeit:
    Als Du das Audio System eingeführt hast, hast Du auch das ICarMetadata Interface um ein Audio Property erweitert. Das solltest Du noch mal abbilden.

    Viele Grüße
    Uwe

  2. Hy, Stefan, in dem Interface ist auf einmal der namespace “CarContract”. In Deinem Sample01 ist der namespace CarHost.

    Was ist denn nun richtig??

    Als Anfänger ist das sehr verwirrend.

    Liebe Grüße

    Alex

  3. Hallo Alex,
    die einzelnen Assemblies können verschiedene Namespaces haben; warum auch nicht? Host, Contract und AddIns liegen bei meinen Beispielen in separate Assemblies. Die Beispiele für Visual Studio, die du dir runterladen kannst, helfen dir hoffentlich weiter.

    Stefan

  4. Danke für die rasche Antwort.
    Prima Artikel. Ich habe zum erstenmal die Funktion des MEF verstanden. Jetzt heißt es üben, üben, üben….

  5. Hallo Stefan, eine kurze Verständnisfrage:

    Bei dem letzten Beispiel mit den drei Listen (1 unshared, 2 shared, also mit Sebastian, Michael und Stefan): welche Creation Policy ist hier für den Export eingestellt? Deinen Ausführungen von oben nach müsste das doch dann Any (bzw. ohne Angabe) sein, oder täusche ich mich da?

    (der Sourcecode zu diesem Beispiel ist in den Samples nicht vorhanden)

    Gruß
    Rolf

    1. Hallo Rolf,
      als Grundlage kannst du Sample06 benutzen. Die Methode Run() muss dann wie folgt aussehen:

      var catalog = new DirectoryCatalog(“.”);
      var container = new CompositionContainer(catalog);
      container.ComposeParts(this);
      foreach (Lazy car in CarPartsA)
      Console.WriteLine(car.Value.StartEngine(“Sebastian”));
      Console.WriteLine(“”);
      foreach (Lazy car in CarPartsB)
      Console.WriteLine(car.Value.StartEngine(“Michael”));
      Console.WriteLine(“”);
      foreach (Lazy car in CarPartsC)
      Console.WriteLine(car.Value.StartEngine(“Stefan”));
      container.Dispose();

      Bei den Exports muss
      [PartCreationPolicy(CreationPolicy.Any)]
      angegeben werden. Alternativ kann das Attribut PartCreationPolicy entfallen.

      Stefan

  6. Hallo Stefan,

    nochmals eine wahrscheinlich typische Anfängerfrage.

    Ich habe gerade Dein Beispiel 4 ausprobiert, da ich aktuell gerade an einem Teilproblem eines größeren Projektes sitze, das vom formalen Aufbau her nahezu identisch ist. Mir ist jetzt aufgefallen, dass bei allen Autoklassen mindestens eine Zeile

    [CarMetadataAudio(AudioSystem.———)]

    erforderlich ist. Wenn man z.B. bei der Merdesklasse diese Zeile auskommentiert (ein Mercedes ohne Audiosystem? – na gibt es sowas?…), kommt es zu einer CompositionContractMismatchException

    “Unable to create an Instance of the Metadata view ‘CarContract.ICarMetadata’ because the exporter exported the metadata for the item ‘Audio’ with the value ‘Without’ as type ‘CarContract.AudioSystem’ but the view imports it as type ‘CarContract.AudioSystem[]’.”
    ,

    wenn im Interface ICarMetadata der Eintrag [DefaultValue(AudioSystem.Without)] drinsteht.

    Der Exporttyp AudioSystem passt nicht mit dem Importtyp Array AudioSystem[] zusammen, wenn AudioSystem.Without als Default drinsteht. Leuchtet mir auch irgendwie ein.

    Aber wie realisiert man dann am besten ein leeres Array AudioSystem[] in den Metadaten?

    Bem.: Beim Ersetzen des Eintrags durch “[DefaultValue(null)]” wird zwar keine Exception mehr geworfen und die Metadaten zum anderen Auto BMW kommen auch richtig, aber das kann wohl kaum eine besonders sinnvolle Lösung sein, da dann anstelle eines Arrays eine Nullreference vorhanden wäre, die man im Composable Part abfangen müsste.)

    Gruß
    Rolf

    1. Hi Rolf,

      teste mal folgendes Attribut:

      [DefaultValue((object)(new AudioSystem[0]))]
      AudioSystem[] Audio { get; }

      Der Defaultwert wird dadurch eine leere Liste vom Typ AudioSystem[].

      Stefan

      1. Statt
        [DefaultValue((object)(new AudioSystem[0]))]
        würde ich
        [DefaultValue(new [] {AudioSystem.Without}]
        nehmen.
        Dann hat man nicht ne leere Liste sondern den ursprünglich gewollten Default Wert als einziger Wert in dem Array.

  7. Super Artikel, leider fehlt im Car-Beispiel Variante 2 (typsicherer Zugriff) wie man das Interface ICarMetadata als ExportMetadata-Attribut angeben muss…

Leave a comment