| 

.NET C# Java Javascript Exception

0
Klassen, welche die Attribute Import und Export enthalten, können von anderen Klassen geerbt werden. Das Verhalten vom Managed Extensibility Framework (MEF) hat hierbei einige Besonderheiten, auch in Bezug auf mögliche Metadaten. Hilfestellung bietet das Attribut InheriedExport. Enthält eine Klasse das Attribut Export, so wird dieses nicht an Unterklassen vererbt. Die Unterklasse kann nicht von MEF [...]

Klassen, welche die Attribute Import und Export enthalten, können von anderen Klassen geerbt werden. Das Verhalten vom Managed Extensibility Framework (MEF) hat hierbei einige Besonderheiten, auch in Bezug auf mögliche Metadaten. Hilfestellung bietet das Attribut InheriedExport.

Enthält eine Klasse das Attribut Export, so wird dieses nicht an Unterklassen vererbt. Die Unterklasse kann nicht von MEF gefunden und mit anderen Parts verbunden werden. Importe verhalten sich genau entgegengesetzt. Das Attribut Import wird immer vererbt. Somit ist eine Klasse, die ein Import geerbt hat, ebenfalls ein Composable Part.

[Export]
public class ClassOne
{
 [Import]
 public object ImportParts { get; set; }
}
public class ClassTwo : ClassOne
{
 // ...
}

Die Eigenschaft ImportParts erbt die Klasse ClassTwo von ClassOne. Da das Attribut Import ebenfalls vererbt wird, kann die Eigenschaft ImportParts der Klasse ClassTwo mit kompatiblen Parts gebunden werden. Gewöhnliche Exports werden nicht geerbt, sodass die Klasse ClassTwo keine Daten exportiert.

Das Attribut InheritedExport

Das Verhalten ändert sich, wenn statt des Attributs Export, das Attribut InheritedExport benutzt wird. Unterklassen, die von solchen Klassen erben, erben auch den gleichen Export, einschließlich des Vertragstyps und des Vertragsnamens. Einzige Einschränkung: Das Attribut InheritedExport kann nur auf Klassen und Schnittstellen angewendet werden, nicht auf Memberebene.

[InheritedExport]
public class ClassOne
{
 [Export]
 public object ExportParts { get; set; }

 [Import]
 public object ImportParts { get; set; }
}
public class ClassTwo : ClassOne
{
 // ...
}

Die Klasse ClassTwo erbt von der Klasse ClassOne. Da ClassOne das Attribut InheritedExport verwendet, erbt ClassTwo den Export von ClassOne, inklusive dem Vertragstyp. Die Eigenschaft ExportParts erbt die Klasse ClassTwo zwar ebenfalls, allerdings ohne das Attribut Export. Exports auf Memberebene werden niemals vererbt. Das Attribut InheritedExport hat keinen Einfluss auf Importe. Die Eigenschaft ImportParts wird inklusive dem Attribut Import an ClassTwo vererbt.

Vererbung von Metadaten

Metadaten werden durch das Attribut InheritedExport ebenfalls vererbt. Diese geerbten Metadaten können von Unterklassen nicht verändert oder durch zusätzliche Metadaten ergänzt werden. Allerdings können durch erneutes Dekorieren der Klasse mit dem Attribut InheritedExport neue Metadaten deklariert werden. Vertragstyp und Vertragsname müssen hierbei die gleichen sein, wie bei der Basisklasse. Ansonsten wird ein weiterer, unabhängiger Export erstellt. Daraus ergibt sich die Tatsache, dass bei einem InheritedExport der Vertragsname und Vertragstyp immer angegeben werden müssen.

Bei dem folgenden Beispiel erben zwei Klassen (die Klassen Mercedes und BMW) von einer gemeinsamen Basisklasse (CarBase).

using System;
using System.ComponentModel.Composition;

namespace CarContract
{
 [InheritedExport(typeof(ICarContract))] 
 [ExportMetadata("Name", "no name")]
 [ExportMetadata("Color", "no color")]
 public class CarBase : ICarContract
 {
 public virtual string StartEngine(string name)
 {
 return String.Format("{0} starts the BaseCar.", name);
 }
 }
}

Bei Mercedes werden keine Metadaten oder das Attribut Export angegeben. Beides wird von CarBase geerbt.

using System;
using CarContract;

namespace CarMercedes
{
 public class Mercedes : CarBase
 {
 public override string StartEngine(string name)
 {
 return String.Format("{0} starts the Mercedes.", name);
 }
 }
}

Die Klasse BMW wird mit den Attributen InheritedExport und ExportMetadata erneut dekoriert. Somit erhält BMW komplett neue Metadaten.

using System;
using System.ComponentModel.Composition;
using CarContract;

namespace CarBMW
{
 [InheritedExport(typeof(ICarContract))]
 [ExportMetadata("Name", "BMW")]
 [ExportMetadata("Price", (uint)40000)]
 public class BMW : CarBase
 {
 public override string StartEngine(string name)
 {
 return String.Format("{0} starts the BMW.", name);
 }
 }
}

Nach der Ausführung des Programms ist gut zu erkennen, dass die Klasse Mercedes die gleichen Metadaten hat wie die Basisklasse. Die Klasse BMW enthält dagegen komplett neue Metadaten.

Unbenannt

Allerdings ist es störend, dass die Basisklasse CarBase ebenfalls ein Composable Part ist. Dieses ist nicht immer erwünscht. Abhilfe schafft hier die Verwendung von Schnittstellen.

Beispiel 1 (Visual Studio 2010)

Schnittstellen

Die Attribute Import und Export können nicht an Schnittstellen angegeben werden, da Schnittstellen nicht direkt instanziiert werden können. Eine Schnittstelle kann allerdings auf Schnittstellenebene mit dem Attribut InheritedExport dekoriert werden. Dieser Export (mit den Metadaten) wird von jeder beliebigen Klasse geerbt. Das obige Beispiel braucht nur so angepasst werden, dass aus der Basisklasse CarBase eine Schnittstelle wird: ICarBase. Da ICarContract schon die Methode StartEngine definiert und ICarBase von ICarContract abgeleitet ist, kann die Methode in ICarBase entfallen.

using System;
namespace CarContract
{
 public interface ICarContract
 {
 string StartEngine(string name);
 }
}

using System;
using System.ComponentModel.Composition;
namespace CarContract
{
 [InheritedExport(typeof(ICarContract))] 
 [ExportMetadata("Name", "no name")]
 [ExportMetadata("Color", "no color")]
 public interface ICarBase : ICarContract { }
}

Bei der Ausführung des Beispiels ist zu erkennen, dass nur noch zwei Composable Parts vorhanden sind.

Unbenannt2

Beispiel 2 (Visual Studio 2010)

Benutzerdefinierte Exportattribute

Die Attribute Export und InheritedExport können so erweitert werden, dass in den Attributeigenschaften die Metadaten enthalten sind. Diese Art der benutzerdefinierten Attribute beinhaltet Vertragsname, Vertragstyp und die Metadaten. Das Deklarieren der Composable Parts wird hierdurch erheblich vereinfacht, insbesondere wenn die Metadaten umfangreich und bei vielen Parts benötigt werden.

Im 2. Teil zum MEF ‘Metadaten und Erstellungsrichtlinien’ wurden schon vier Arten der benutzerdefinierten Attribute vorgestellt. Das folgende Bespiel stellt eine weitere Variante da.

Bei diesem Beispiel werden die Metadaten durch die Klasse CarAttribute dargestellt. Diese Klasse muss mit dem Attribut MetadataAttribute dekoriert werden. Zusätzlich wird die Klasse von ExportAttribute oder InheritedExportAttribute abgeleitet. Somit stellt diese auch das Attribut Export bereit. Der Konstruktor leitet den Vertragstyp ICarContract an die Klasse ExportAttribute weiter.

using System;
using System.ComponentModel.Composition;

namespace CarContract
{
 [MetadataAttribute]
 [AttributeUsage(AttributeTargets.Class)]
 public class CarAttribute : ExportAttribute
 {
 public CarAttribute()
 : base(typeof(ICarContract))
 {
 // set default values
 this.Name = "noName";
 this.Color = CarColor.Unkown;
 this.Price = 0;
 }

 public string Name { get; set; }
 public CarColor Color { get; set; }
 public uint Price { get; set; }
 }
}

Die Klasse CarAttribute definiert ein benutzerdefiniertes Attribut mit den Namen Car und den Vertragstyp ICarContract. Das Dekorieren einer Klasse mit dem Attribut Car sieht wie folgt aus:

[Car(Name="Mercedes", Color=CarColor.Blue, Price=48000)] 
public class Mercedes : ICarContract
{
 public string StartEngine(string name)
 {
 return String.Format("{0} starts the Mercedes.", name);
 }
}

Ohne die Klasse CarAttribute müssten die Metadaten und der Vertragstyp separat angegeben werden, was deutlich aufwendiger wäre.

[Export(typeof(ICarContract))]
[ExportMetadata("Name", "Mercedes")]
[ExportMetadata("Color", CarColor.Blue)] 
[ExportMetadata("Price", (uint)48000)]
public class Mercedes : ICarContract
{
 public string StartEngine(string name)
 {
 return String.Format("{0} starts the Mercedes.", name);
 }
}

Beispiel 3 (Visual Studio 2010)

Im nächsten Teil geht es dann um die Kataloge und Container.


vererbung mef managed-extensibility-framework composable-parts metadaten inheritedexport
Weitere News:
Schreibe einen Kommentar:
Themen:
inheritedexport metadaten composable-parts managed-extensibility-framework mef vererbung
Entweder einloggen... ...oder ohne Wartezeit registrieren
Benutzername
Passwort
Passwort wiederholen
E-Mail