2010-04-16 3 views
17

Gibt es eine Möglichkeit, Automapper automatisch für die Suche nach allen Profilen im Namespace/Assembly zu konfigurieren? Was würde Ich mag tun Mapping-Profile zu AutoMapper aus gegebener Montage durch bestimmte Schnittstelle, so etwas wie Scan-Konventionen in StructureMap gefiltert hinzuzufügen:Wie werden Profile in AutoMapper gescannt und automatisch konfiguriert?

public static void Configure() 
    { 
     ObjectFactory.Initialize(x => 
      { 
       // Scan Assembly 
       x.Scan(
        scanner => 
        { 
         scanner.TheCallingAssembly(); 
         scanner.Convention<MyCustomConvention>(); 
         scanner.WithDefaultConventions(); 
        }); 

       // Add Registries 
       x.AddRegistry(new SomeRegistry()); 
      }); 

     Debug.WriteLine(ObjectFactory.WhatDoIHave()); 
    } 

public class MyCustomConvention : IRegistrationConvention 
{ 
    public void Process(Type type, Registry registry) 
    { 
     if (!type.CanBeCastTo(typeof(IMyType))) 
     { 
      return; 
     } 

     string name = type.Name.Replace("SomeRubishName", String.Empty); 
     registry.AddType(typeof(IMyType), type, name);    
    } 

Ich habe versucht SelfConfigure zu verwenden, aber keine Dokumentation nicht finden kann auf wie es verwenden, um Profile herauszufiltern:

public static void Configure() 
    { 
     Mapper.Initialize(x => 
           { 
            // My Custom profile 
            x.AddProfile<MyMappingProfile>(); 

            // Scan Assembly 
            x.SelfConfigure(Assembly.GetCallingAssembly()); 
           }); 
    } 

Eine andere Frage ist, wie kann ich alle Karten/Profile berichten bereits initialisiert (so etwas wie ObjectFactory.WhatDoIHave() in StructureMap)?

Antwort

31

fand ich diesen Beitrag, während auch die Suche, aber das ist, wie ich ein Auto-Zuordnungsschema umgesetzt:

public class MyCustomMap : Profile 
{ 
    protected override void Configure() 
    { 
     CreateMap<MyCustomViewModel, MyCustomObject>() 
      .ForMember(dest => dest.Phone, 
         opt => opt.MapFrom(
         src => src.PhoneAreaCode + src.PhoneFirstThree + src.PhoneLastFour)); 
    } 
} 

public static class AutoMapperConfiguration 
{ 
    public static void Configure() 
    { 
     Mapper.Initialize(x => GetConfiguration(Mapper.Configuration)); 
    } 

    private static void GetConfiguration(IConfiguration configuration) 
    { 
     var profiles = typeof(MyCustomMap).Assembly.GetTypes().Where(x => typeof(Profile).IsAssignableFrom(x)); 
     foreach (var profile in profiles) 
     { 
      configuration.AddProfile(Activator.CreateInstance(profile) as Profile); 
     } 
    } 
} 

Also, wenn meine Anwendung startet, alles, was ich nennen ist

AutoMapperConfiguration.Configure(); 

Und alle meine Karten sind registriert.

+0

Dies scheint sich mit der ConstructServicesUsing-Methode gegenseitig zu vermeiden. Kämpfen mit passierenden Abhängigkeiten atm. –

+0

Ja, ich gebe keine Abhängigkeiten in meinen Karten. Sie könnten sie immer in einem IoC-Container registrieren und die Abhängigkeiten für Sie auflösen lassen. Wir hätten das getan, aber es war nicht nötig. –

+2

Arnis L - ändern Sie einfach configuration.AddProfile (Activator.CreateInstance (Profil) als Profil); zu configuration.AddProfile (ServiceLocator.Current.GetInstance (Profil) als Profil); (oder ähnlich, hängt natürlich davon ab, welchen IoC-Container Sie verwenden), um die Abhängigkeitsinjektion zu aktivieren. Gute Antwort. –

6

Ja, das wäre fantastisch ... und genau das, was ich für V2 überhole. Scannen, Registrierung, Konventionen usw.

Es ist kein gutes „Was muss ich“ -Funktion, aber ich denke, es ist auf jeden Fall lohnen würde hinzufügen.

+0

Vielen Dank für AutoMapper - Ich und viele andere wären ohne sie verloren. Gibt es einen Blog-Post (oder E-Mail-Thread/Artikel/SO-Post) darüber, wie "Profile" und Freunde dort verwendet werden sollten, von denen du weißt? Gerade jetzt, SO, die Dinge sind ein bisschen verwirrend, da es viele Beispiele für die v1-Ära gibt, aber vorherige kleine v2-Sachen. Sogar ein Satz, wie 'Rig Ihre DI, um IXXXInitialize impls abholen, und für diejenigen, die an den ctor von XXXConfiguration und dann z. Controller, die Mapper benötigen, die an IMapper gebunden sind, was durch IConfiguration 'oder etwas ähnliches implementiert wird. –

1

Ich habe es so ist, weiß nicht, ob es der beste Weg ist, aber es funktioniert sehr gut auf ziemlich großes Projekt.

public class AutoMapperGlobalConfiguration : IGlobalConfiguration 
    { 
     private AutoMapper.IConfiguration _configuration; 

     public AutoMapperGlobalConfiguration(IConfiguration configuration) 
     { 
      _configuration = configuration; 
     } 

     public void Configure() 
     { 
      //add all defined profiles 
      var query = this.GetType().Assembly.GetExportedTypes() 
       .Where(x => x.CanBeCastTo(typeof(AutoMapper.Profile))); 

      _configuration.RecognizePostfixes("Id"); 

      foreach (Type type in query) 
      { 
       _configuration.AddProfile(ObjectFactory.GetInstance(type).As<Profile>()); 
      } 

      //create maps for all Id2Entity converters 
      MapAllEntities(_configuration); 

      Mapper.AssertConfigurationIsValid(); 
     } 

     private static void MapAllEntities(IProfileExpression configuration) 
     { 
      //get all types from the SR.Domain assembly and create maps that 
      //convert int -> instance of the type using Id2EntityConverter 
      var openType = typeof(Id2EntityConverter<>); 
      var idType = typeof(int); 
      var persistentEntties = typeof(SR.Domain.Policy.Entities.Bid).Assembly.GetTypes() 
       .Where(t => typeof(EntityBase).IsAssignableFrom(t)) 
       .Select(t => new 
       { 
        EntityType = t, 
        ConverterType = openType.MakeGenericType(t) 
       }); 
      foreach (var e in persistentEntties) 
      { 
       var map = configuration.CreateMap(idType, e.EntityType); 
       map.ConvertUsing(e.ConverterType); 
      } 
     } 
    } 
} 
+0

Mit diesem - ich denke, Sie können den Lebenszyklus von Profilabhängigkeiten nicht steuern. –

0
public class AutoMapperAdapter : IMapper 
{ 
    private readonly MapperConfigurationExpression _configurationExpression = 
     new MapperConfigurationExpression(); 

    public void AssertConfigurationIsValid() { Mapper.AssertConfigurationIsValid(); } 

    public void CreateMap<TSource, TDestination>() 
    { 
     _configurationExpression.CreateMap<TSource, TDestination>(); 
    } 

    public void Initialize() { Mapper.Initialize(_configurationExpression); } 

    public TDestination Map<TDestination>(object source) 
    { 
     return Mapper.Map<TDestination>(source); 
    } 
} 
5

In den neuesten Versionen von AutoMapper ist es möglich, mehr Profil Scannen ein oder mehr Baugruppen registrieren.

Mapper.Initialize(x => x.AddProfiles(typeof(MyMappingProfile).Assembly)); 

Getestet mit AutoMapper v 6.0.2.0

Verwandte Themen