2011-09-27 45 views
2

我使用ASP.NET MVC 3RazorAutofac爲依賴注入。通用映射器,而不是有大量的個人映射器

我正在考慮創建一個通用映射器。目前我正在使用AutoMapper作爲我的域和視圖模型之間的映射。它可以是任何映射框架,但我使用的是AutoMapper。

這裏是我的IMapper接口:

public interface IMapper 
{ 
    object Map(object source, Type sourceType, Type destinationType); 
} 

然後我有一個實現這個IMapper接口的IBankMapper接口。我之所以這樣做是因爲我可以有許多不同的映射器。使用依賴注入我可以知道我可以注入哪個實例。所以對於IBankMapper我會注入BankMapper,ICategoryMapper我會注入CategoryMapper。

IBankMapper接口:

public interface IBankMapper : IMapper 
{ 
} 

BankMapper類:

public class BankMapper : IBankMapper 
{ 
    static BankMapper() 
    { 
      Mapper.CreateMap<Bank, EditBankViewModel>(); 
      Mapper.CreateMap<EditBankViewModel, Bank>(); 
    } 

    public object Map(object source, Type sourceType, Type destinationType) 
    { 
      return Mapper.Map(source, sourceType, destinationType); 
    } 
} 

隨着程序的增長因此將映射器類。有沒有一種方法可以創建一個通用映射器,一個可以在整個應用程序中使用的映射器?這可能嗎?

+1

我不明白你的問題。 AutoMapper *是一個通用的映射器... –

+0

我想教我的映射器類。我有BankMapper,AccountTypeMapper,ProductMapper,ApplicationMapper等。我想嘗試創建1個接受源類和目的類的映射類(如果可能的話)。像TSource和TDestination一樣。 –

回答

5

完全不需要您創建任何映射器類。

您只需確保在申請開始時致電Mapper.CreateMap即可。然後你可以使用Mapper.Map來做你的映射。

通常,我使用單一方法創建一個靜態類來處理我的地圖的創建。它看起來像這樣:

public static class Transformers 
{ 
    public static void Register() 
    { 
     Mapper.CreateMap<Bank, EditBankViewModel>(); 
     Mapper.CreateMap<EditBankViewModel, Bank>(); 

     Mapper.CreateMap<Account, EditAccountViewModel>(); 
     Mapper.CreateMap<EditAccountViewModel, Account>(); 

     // And so on. You can break them up into private methods 
     // if you have too many. 
    } 
} 

然後我在Global.asax中調用該方法確保它在必要時運行。在我的應用程序的任何其他地方,我可以自由地調用Mapper.Map任何配置的映射:

protected void Application_Start() 
{ 
    Transformers.Register(); 
} 
+0

您能否爲我提供一個將視圖模型映射到域模型的單元測試以及如何在您的控制器中實現這一點? –

1

正如丹尼爾說,Automapper已經是一個通用的映射。如果你擔心的直接依賴於你的代碼automapper,你可以將其隱藏一個小門面後面,如:

public interface IMapper 
{ 
    TDestination Map<TSource, TDestination>(TSource source); 
} 
public class MyMapper :IMapper 
{ 
    public TDestination Map<TSource, TDestination>(TSource source) 
    { 
     AutoMapper.Mapper.CreateMap<TSource, TDestination>(); 
     return AutoMapper.Mapper.Map<TSource, TDestination>(source); 
    } 
} 

這也可以幫助你的映射模型作爲注射依賴

+0

不需要這樣做。 AutoMapper已經提供了這樣一個接口! –

+1

@DanielHilgarth我不知道,謝謝你的評論。也就是說,有些人不想依賴「外部定義的」接口,這種解決方案仍然可以用於這些情況。 – jeroenh

+0

我同意:如果對具體自動映射器的接口的依賴性是一個問題,那麼您的Facade接口將有所幫助,並且是一條可行的路。但是,它看起來不像是OPs問題。 –

4

看起來您正在創建這些接口,以便能夠在單元測試中模擬AutoMapper。爲此,您可以簡單地使用AutoMapper的IMappingEngine

你的課程將依賴IMappingEngine這將被注入。 IMappingEngine與靜態類Mapper具有相同的方法來映射您的對象。

在您的作文根中,您可以配置映射器並將映射引擎註冊到DI容器。

事情是這樣的:

// composition root: 
Mapper.CreateMap<Bank, EditBankViewModel>(); 
Mapper.CreateMap<EditBankViewModel, Bank>(); 
builder.Register(Mapper.Engine); 

// your classes: 
class YourClass 
{ 
    public YourClass(IMappingEngine mappingEngine) 
    { 
    } 
} 
+0

好東西.... – jeroenh