Navigation and service panel


Content

This text is fallbacked from the German Version. If you need use Google Translate


Sprachunabhängige Referenzen mit Glass Mapper

By Kevin Brechbühl on 22. February 2014, No comments

In einem aktuellen Projekt haben wir uns entschieden, Glass Mapper als ORM einzusetzen, um die Items in Sitecore automatisch zu typsicheren Objekten im Code zu konvertieren. Glass Mapper prüft standardmässig beim Laden eines Items immer auf eine gültige Sprachversion. Dies ist ein super Feature für das Hauptitem. Was aber, wenn das Item eine Referenz auf ein Item hat (z.B. einen Droplink), welches nur shared Felder hat und somit meist auch nur in einer Sprache vorhanden ist?

Es gibt in unserem Projekten immer wieder Konfigurationen, welche wir in Sitecore ablegen. Für solche Konfiguration definieren wir ein Template Specification mit einem Feld für den Wert der Konfiguration.

Specification

Unser Inhaltsitem besitzt z.B. eine solche Konfiguration für den Typ eines Containers (via Droplink). Vereinfacht sieht unsere Konfiguration für Glass Mapper und unser Feld wie folgt aus:

[SitecoreField(FieldName = "Container Type")]
public virtual Specification ContainerType { get; set; }

Dies funktioniert nun leider nur, wenn das Specification Item in jeder jeweiligen Sprache vorhanden ist die wir laden. Um dies zu umgehen brauchen wir mehrere Teile.

Eigenes SitecoreSharedField Attribut

Das Attribut brauchen wir, um Glass Mapper mitzuteilen wie das entsprechende Property beim Mapping der Daten behandelt werden soll. Das Attribut identifiziert eigentlich nur das Item und erstellt eine eigene Konfiguration:

public class SitecoreSharedFieldAttribute : SitecoreFieldAttribute
{
    public override AbstractPropertyConfiguration Configure(PropertyInfo propertyInfo)
    {
        var config = new SitecoreSharedFieldConfiguration();
        this.Configure(propertyInfo, config);
        return config;
    }
}

Konfiguration für das Attribut

Jedes Attribut in Glass Mapper hat eine eigene Konfiguration, so auch unser eigenes Attribut. Die Konfiguration welches unser Attribut verwendet müssen wir ebenfalls implementieren. Hier ist eigentlich nur wichtig die Methode Copy() zu überschreiben, damit eine korrekte Instanz retourniert wird:

public class SitecoreSharedFieldConfiguration : SitecoreFieldConfiguration
{
    public override SitecoreFieldConfiguration Copy()
    {
        return new SitecoreSharedFieldConfiguration
        {
            CodeFirst = this.CodeFirst,
            FieldId = this.FieldId,
            FieldName = this.FieldName,
            FieldSource = this.FieldSource,
            FieldTitle = this.FieldTitle,
            FieldType = this.FieldType,
            IsShared = this.IsShared,
            IsUnversioned = this.IsUnversioned,
            PropertyInfo = this.PropertyInfo,
            ReadOnly = this.ReadOnly,
            SectionName = this.SectionName,
            Setting = this.Setting
        };
    }
}

Eigener Data Mapper für die Funktionalität

Bis jetzt haben wir Glass Mapper nur mitgeteilt, dass wir etwas spezielles mit unserem Property vorhaben, aber noch nicht was. Dazu brauchen wir einen eigenen Data Mapper. Bei der Initialisierung von Glass Mapper wird jedem Property ein Mapper zugewiesen. Welches Property welchen Mapper erhält wird über die Methode CanHandle() entschieden (also alle Properties mit unserem Attribut, ausser Listentypen, welche durch Glass Mapper speziell behandelt werden). Die Methode GetFieldValue() ruft schlussendlich nur den Standard Field Mapper auf, mit deaktivierter Versionsüberprüfung:

public class SitecoreSharedFieldTypeMapper : SitecoreFieldTypeMapper
{
    public override object GetFieldValue(string fieldValue, SitecoreFieldConfiguration config, SitecoreDataMappingContext context)
    {
        using (new VersionCountDisabler())
        {
            return base.GetFieldValue(fieldValue, config, context);
        }
    }

    public override bool CanHandle(AbstractPropertyConfiguration configuration, Context context)
    {
        return configuration is SitecoreSharedFieldConfiguration && !configuration.PropertyInfo.PropertyType.IsGenericType;
    }
}

Mehr Informationen zu eigenen Data Mappers sind in diesem Tutorial zu finden.

Konfiguration des eigenen Mappers

Beim initialisieren von Glass Mapper muss nun noch der eigene Data Mapper registriert werden. Dies wird in der Klasse App_Start/GlassMapperScCustom.cs (bei der Standardinstallation unter der Verwendung von Castle Windsor) gemacht:

public static void CastleConfig(IWindsorContainer container)
{
    var config = new Config();
    container.Register(Component.For <AbstractDataMapper>().ImplementedBy<SitecoreSharedFieldTypeMapper>().LifeStyle.Transient);
    container.Install(new SitecoreInstaller(config));
}

Nun müssen wir nur noch die Definition unseres Items anpassen, damit das eigene Attribut verwendet wird:

[SitecoreSharedField(FieldName = "Container Type")]
public virtual Specification ContainerType { get; set; }

Das Gleiche funktioniert übrigens auch mit Listen (z.B. Multilist), dazu muss das Feld einfach wie folgt konfiguriert werden:

[SitecoreSharedField(FieldName = "Available Languages")]
public virtual IEnumerable<Specification> AvailableLanguages { get; set; }

Ich möchte mich an dieser Stelle noch ganz herzlich bei Mike Edwards, Entwickler von Glass Mapper, bedanken. Er hat mir an einigen Wochenenden geholfen, diesen Code zu schreiben und zu debuggen.

Categories  Libraries  Modules Tags  Glass Mapper  ORM  Sprachen

No comments

Add your comment

Your email address will not be published. Required fields are marked *

*