我的ASP.NET MVC 3应用程序的服务层使用AutoMapper将视图模型映射到业务对象。我实现了类型转换器,将post / get请求中提交的对象ID转换为业务对象.Type转换器通过ID查找数据库中的实体,并从中重建业务。例如:
class UserViewModel {
// user fields
Guid? Manager; // this is an ID of another user in the system
}
服务将调用AutoMapper:
var userModel = Mapper.Map<UserViewModel, UserModel>(viewModel);
映射到此类:
class UserModel {
// other fields...
UserModel Manager;
}
借助类型转换器,通过View GUID从视图模型中查找数据库中的另一个用户。使用Ninject为类型转换器注入依赖关系,一切都在Web应用程序中正常工作。
我正在尝试编写单元测试,它将使用带有类型转换器的模拟存储库。可以将AutoMapper配置为使用用户提供的功能构建服务:
Mapper.Initialize(cfg =>
{
cfg.ConstructServicesUsing(type => Kernel.GetService(type));
});
在Web应用程序中,Kernel是Ninject,对于测试,我决定提供自己的方法,从字典中返回所请求类型的实例:
Dictionary<Type, object> typeDict = new Dictionary<Type, object>()
{
{ typeof(IRepository), new MockRepository() }
};
...
Mapper.Initialize(cfg =>
{
cfg.ConstructServicesUsing(type => { return typeDict[type]; } );
});
这个想法是当AutoMapper配置为将Guid转换为这样的对象时:
Mapper.CreateMap<Guid?, TDropDown>()
.ConvertUsing<GuidToSelectListValueConverter<TDropDown>>();
并且需要创建GuidToSelectListValueConverter的新实例并将其注入存储库,它将使用ConstructServicesUsing中配置的方法请求IRepository类型。
相反,AutoMapper实际上尝试获取GuidToSelectListValueConverter类型的实例。这意味着我负责创建类型转换器的新实例并为其注入依赖项。我的typeDict应该是这样的:
Dictionary<Type, object> typeDict = new Dictionary<Type, object>()
{
{ typeof(GuidToSelectListValueConverter), new GuidToSelectListValueConverter(
new MockRepository()) }
};
我确实有很多类型转换器,并且手动编写解析器函数似乎不可行。这让我思考。在我的单元测试中简单地配置Ninject来解决这些依赖关系是不是错了?我可以将IRepository绑定到MockRepository,然后当我需要一个服务实例时,只需调用Kernel.GetService(typeof(MyService))并让Ninject用MockRepository注入它。额外的好处是AutoMapper还将使用Ninject来获取类型转换器和值解析器的实例:
// configure Ninject
Kernel.Bind<IRepository>().To<MockRepository>();
// initialize AutoMapper
Mapper.Initialize(cfg =>
{
cfg.ConstructServicesUsing(t => Kernel.GetService(t));
});
// create an instance of service to test
var service = Kernel.GetService(IMyService);
// do work
var result = service.DoWork();
// analyze result
现在,当DoWork方法调用Mapper.Map类型转换器时,使用Ninject创建。
欢迎任何建议,想法和最佳实践建议。
谢谢!
答案 0 :(得分:1)
查看this post on using IoC with AutoMapper。
这有助于我在控制器中使用IMappingEngine
代替Mapper
,朝着正确的方向前进。