Für Mapping mehrere IMapper die mit verschiedenen MapperConfiguration Objekte, die eine etwas immer wieder auftretendes Problem scheint zu sein, empfehle ich die folgende Vorgehensweise, die nicht einmal braucht die Mapper-Methode aufruft Refactoring:
1) Erstellen einer generischen Wrapper um die IMapper-Schnittstelle. Dieser Wrapper kann entweder eine Schnittstelle oder eine Klasse sein, aber offensichtlich müssen Sie Ihren Wrapper implementieren, daher werde ich die konkrete Klasse unten zeigen. Lassen Sie sich diese Wrapper implementieren (oder erben, wenn Sie eine Schnittstelle machen wählte) die IMapper Schnittstelle, etwa so:
public class ProfileMapper<TProfile> : IMapper where TProfile : Profile
{
private IMapper mapper;
private Profile profile;
public ProfileMapper(TProfile profile)
{
this.profile = profile;
this.mapper = new MapperConfiguration(cfg => cfg.AddProfile(this.profile))
.CreateMapper();
}
}
Das generische Argument muss eine Unterklasse von „Profil“ sein, denn von diesem Profil ist, wo Sie sind werde deine Mapper-Konfiguration bekommen.
2) In dieser Klasse implementieren die IMapper Schnittstelle einfach durch die Anrufe an die privaten IMapper Instanz umgeleitet, die Sie im Konstruktor, etwa so:
public TDestination Map<TDestination>(object source)
{
return mapper.Map<TDestination>(source);
}
3) Nun müssen Sie in der Einfachen registrieren Injector eine teilweise geschlossene Instanz dieser ProfileMapper-Klasse für jedes Profil, das Sie haben. Sie tun dies zuerst, indem Sie alle Klassen erhalten, die von Profil erben, dann diese teilweise geschlossene Instanz erstellen und dann registrieren. Es gibt mehrere Wege, um alle Profilklassen, aber ich ging mit diesem:
IEnumerable<Type> profileRegistrations =
from type in profileAssembly.GetExportedTypes()
where type.Namespace == "Namespace.Of.My.Profiles"
where type.BaseType.Equals(typeof(Profile))
select type;
foreach (Type profileType in profileRegistrations)
{
Container.RegisterSingleton(profileType, profileType);
Type mapperClosedType = typeof(ProfileMapper<>).MakeGenericType(profileType);
Container.RegisterSingleton(typeof(ProfileMapper<>), mapperClosedType);
}
Dieser Code zuerst alle Typen bekommt, die von Profil erben, befindet sich in dem Namespace. Dann registriere ich es für jedes Profil mit SimpleInjector (nicht wirklich notwendig, da es sich um konkrete Typen handelt und als solche vom Container im laufenden Betrieb erstellt werden kann), dann mache ich eine teilweise geschlossene Instanz meiner ProfileWrapper-Klasse mit der aktuellen Profil als generisches Argument, und schließlich registriere ich meine geschlossene Instanz als Singleton. Auf diese Weise können Sie neue Profile erstellen, ohne neue Wrapper manuell registrieren zu müssen.
Und das ist es.Statt nun je nach und Einspritzen des IMapper, injizieren Sie Ihre ProfileWrapper mit dem Profil, das Sie verwenden möchten, wie folgt aus:
ProfileMapper<ApplicationProfile> appProfileMapper;
ProfileMapper<MvcProfile> mvcProfileMapper;
ProfileMapper<GuestProfile> guestProfile;
und so weiter. Jeder Wrapper wurde mit einer separaten MapperConfiguration mit verschiedenen Profilen erstellt. Da der Wrapper den IMapper implementiert, bleibt der gesamte Mapping-Code gleich. Es ist nicht notwendig, die Methodenaufrufe zu refactorisieren, nur die Abhängigkeitstypen.
Wenn Sie ein BaseProfile erstellen, ändern Sie einfach den generischen Parameter in ProfileMapper, um nur Instanzen für dieses BaseProfile zu akzeptieren.
Und Sie können die MapperConfigurationstion wahrscheinlich komplett entfernen, da es unwahrscheinlich ist, dass Ihre Komponenten davon abhängen. – Steven
Registrierung der 'MapperConfiguration' ist nur sinnvoll, wenn Sie [LINQ-Projektionen] (https://github.com/AutoMapper/AutoMapper/wiki/Migrating-from-static-API#linq-projections) verwenden. – mrmashal
Wie sieht es mit mehreren MapperConfiguration (en) aus? Ich muss verschiedene Konfigurationen haben, Profile mischen, aber auf diese Weise kann ich nur einen IMapper registrieren. –