2009-09-29 23 views
19

我的當前項目包含用於域模型,MVC Web應用程序和單元測試的程序集。我如何設置AutoMapper配置,以便所有程序集引用相同的配置?如何爲每個AppDomain配置一次AutoMapper

我想我可以把項目放在Global.asax中的web應用程序,但我怎麼能在單元測試中使用它呢?另外,如果配置位於Global.asax中,域模型是否會提取地圖?

非常感謝,

KevDog。

回答

28

我們所做的是創建一個靜態類,像BootStrapper,並將初始化代碼放在一個靜態方法中。我們正在做個人資料,所以你在那裏看不到太多內容。 Global.asax將在啓動時調用它,域將使用它(因爲配置是單例),並且需要它的單元測試在它們的設置中調用BootStrapper.Configure()。

我們做的最後一件事情是在引導程序上保持一個標誌,並在配置時將其設置爲true。這樣,配置僅對每個AppDomain執行一次。這意味着一旦啓動global.asax(Application_Start),並且一次運行單元測試。

HTH

+1

謝謝吉米!在這個工具上工作出色,它在多個層面上都很有用。我喜歡bootstrapper上的國旗。今晚我會把這個插入我的代碼中。 – KevDog 2009-09-30 14:24:33

+0

謝謝!這幫了我很多。至於這個工具,我非常喜歡它! – Rushino 2011-09-20 16:57:32

4

我也使用引導程序來處理這種啓動任務的東西。實際上,我使用了一系列bootstrappers,因爲我像那樣瘋狂。通過Automapper方式,我們發現製作一些AutoMappingBuddy類並使用屬性裝飾它們會很乾淨。然後,我們通過一些反射電話(不便宜,但他們只能在一開始就射擊一次)連接映射器。這個解決方案是在我們厭倦了在1200 +行文件的841行中發現AutoMapper問題後才發現的。


我想過發佈代碼,但我不能真正稱它爲purdy。總之,這裏有雲:

首先,一個簡單的接口,爲AutoMappingBuddies:

public interface IAutoMappingBuddy 
{ 
    void CreateMaps(); 
} 

二,一點點屬性提供一些膠水:

public class AutoMappingBuddyAttribute : Attribute 
{ 
    public Type MappingBuddy { get; private set; } 

    public AutoMappingBuddyAttribute(Type mappingBuddyType) 
    { 
     if (mappingBuddyType == null) throw new ArgumentNullException("mappingBuddyType"); 
     MappingBuddy = mappingBuddyType; 
    } 

    public IAutoMappingBuddy CreateBuddy() 
    { 
     ConstructorInfo ci = MappingBuddy.GetConstructor(new Type[0]); 
     if (ci == null) 
     { 
      throw new ArgumentOutOfRangeException("mappingBuddyType", string.Format("{0} does not have a parameterless constructor.")); 
     } 
     object obj = ci.Invoke(new object[0]); 
     return obj as IAutoMappingBuddy; 
    } 
} 

三,AutoMappingEngine。這是魔術發生的地方:

public static class AutoMappingEngine 
{ 
    public static void CreateMappings(Assembly a) 
    { 
     Dictionary<Type, IAutoMappingBuddy> mappingDictionary = GetMappingDictionary(a); 
     foreach (Type t in a.GetTypes()) 
     { 
      var amba = 
       t.GetCustomAttributes(typeof (AutoMappingBuddyAttribute), true).OfType<AutoMappingBuddyAttribute>(). 
        FirstOrDefault(); 
      if (amba!= null && !mappingDictionary.ContainsKey(amba.MappingBuddy)) 
      { 
       mappingDictionary.Add(amba.MappingBuddy, amba.CreateBuddy()); 
      } 
     } 
     foreach (IAutoMappingBuddy mappingBuddy in mappingDictionary.Values) 
     { 
      mappingBuddy.CreateMaps(); 
     } 
    } 

    private static Dictionary<Type, IAutoMappingBuddy> GetMappingDictionary(Assembly a) 
    { 
     if (!assemblyMappings.ContainsKey(a)) 
     { 
      assemblyMappings.Add(a, new Dictionary<Type, IAutoMappingBuddy>()); 
     } 
     return assemblyMappings[a]; 
    } 

    private static Dictionary<Assembly, Dictionary<Type, IAutoMappingBuddy>> assemblyMappings = new Dictionary<Assembly, Dictionary<Type, IAutoMappingBuddy>>(); 
} 

有點在一個小時左右,有可能更優雅的方式到達那裏。

+0

Wyatt,如果你有機會就你如何做到這一點做一個帖子,我肯定會閱讀它。這聽起來很優雅。 – KevDog 2009-09-30 14:25:06

+0

對於大型配置文件,這可能也會添加到AutoMapper中。 v.next的好主意! – 2009-09-30 14:58:11

+0

已發佈代碼。 @Jimmy:如果您願意,我可以提交補丁,讓我知道它應該放到代碼庫中的位置。 – 2009-09-30 15:37:50

4

我試過上面的代碼,但無法讓它工作。我修改了一下,如下所示。我認爲剩下要做的就是通過Global.asax的Bootstrapper調用它。希望這可以幫助。

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Reflection; 

using AutoMapper; 

namespace Automapping 
{ 
    public class AutoMappingTypePairing 
    { 
     public Type SourceType { get; set; } 
     public Type DestinationType { get; set; } 
    } 

    public class AutoMappingAttribute : Attribute 
    { 
     public Type SourceType { get; private set; } 

     public AutoMappingAttribute(Type sourceType) 
     { 
      if (sourceType == null) throw new ArgumentNullException("sourceType"); 
      SourceType = sourceType; 
     } 
    } 

    public static class AutoMappingEngine 
    { 
     public static void CreateMappings(Assembly a) 
     { 
      IList<AutoMappingTypePairing> autoMappingTypePairingList = new List<AutoMappingTypePairing>(); 

      foreach (Type t in a.GetTypes()) 
      { 
       var amba = t.GetCustomAttributes(typeof(AutoMappingAttribute), true).OfType<AutoMappingAttribute>().FirstOrDefault(); 

       if (amba != null) 
       { 
        autoMappingTypePairingList.Add(new AutoMappingTypePairing{ SourceType = amba.SourceType, DestinationType = t}); 
       } 
      } 

      foreach (AutoMappingTypePairing mappingPair in autoMappingTypePairingList) 
      { 
       Mapper.CreateMap(mappingPair.SourceType, mappingPair.DestinationType); 
      } 
     } 
    } 
} 

我使用這樣的源與目標配對關聯:

[AutoMapping(typeof(Cms_Schema))] 
public class Schema : ISchema 
{ 
    public Int32 SchemaId { get; set; } 
    public String SchemaName { get; set; } 
    public Guid ApplicationId { get; set; } 
} 

然後自動地創建映射,我這樣做:

 Assembly assembly = Assembly.GetAssembly(typeof([ENTER NAME OF A TYPE FROM YOUR ASSEMBLY HERE])); 

     AutoMappingEngine.CreateMappings(assembly); 
2

我一直將我的AutoMapper CreateMap調用移動到我的視圖模型旁邊的類中。他們實現了一個IAutomapperRegistrar接口。我使用反射來查找IAutoMapperRegistrar實現,創建實例並添加註冊。

這裏的接口:

public interface IAutoMapperRegistrar 
{ 
    void RegisterMaps(); 
} 

下面是接口的實現:

public class EventLogRowMaps : IAutoMapperRegistrar 
{ 
    public void RegisterMaps() 
    { 
     Mapper.CreateMap<HistoryEntry, EventLogRow>() 
      .ConstructUsing(he => new EventLogRow(he.Id)) 
      .ForMember(m => m.EventName, o => o.MapFrom(e => e.Description)) 
      .ForMember(m => m.UserName, o => o.MapFrom(e => e.ExecutedBy.Username)) 
      .ForMember(m => m.DateExecuted, o => o.MapFrom(e => string.Format("{0}", e.DateExecuted.ToShortDateString()))); 
    } 
} 

這裏是執行我的Application_Start的註冊代碼:

foreach (Type foundType in Assembly.GetAssembly(typeof(ISaveableModel)).GetTypes()) 
{ 
    if(foundType.GetInterfaces().Any(i => i == typeof(IAutoMapperRegistrar))) 
    { 
     var constructor = foundType.GetConstructor(Type.EmptyTypes); 
     if (constructor == null) throw new ArgumentException("We assume all IAutoMapperRegistrar classes have empty constructors."); 
     ((IAutoMapperRegistrar)constructor.Invoke(null)).RegisterMaps(); 
    } 
} 

我認爲這是合適的,至少有點合乎邏輯;他們更容易遵循這種方式。在我用一種巨大的bootstrap方法進行了數百次註冊之前,這已經開始成爲屁股疼痛了。

想法?

相關問題