我有一个多租户Web应用程序,它有多个模块.我使用autofac作为IOC和Automapper来映射我的模型和实体.在下面的代码中,我能够将UserAuthenticationMapper配置文件添加到automapper,但无法添加CustomerDataMapper配置文件.Autofac仅向自动化MappingEngine添加一个映射器配置文件,并忽略其余部分.我在做什么错了?
这是我的UserAuthentication模块:
public class UserAuthenticationModule: Autofac.Module { protected override void Load(ContainerBuilder builder) { builder.RegisterType().As (); builder.Register(ctx => { var configStore = new ConfigurationStore (new TypeMapFactory(), MapperRegistry.AllMappers()); configStore.AddProfile (); return configStore; }) .AsImplementedInterfaces() .SingleInstance(); var assembly = Assembly.GetExecutingAssembly(); builder.RegisterAssemblyTypes(assembly) .Where(t => t.Name.EndsWith("Service")) .AsImplementedInterfaces() .SingleInstance(); } }
CustomerData Modue:
public class CustomerDataModule : Autofac.Module { protected override void Load(ContainerBuilder builder) { builder.RegisterType() .As () .InstancePerDependency(); builder.RegisterType ().As (); builder.Register(ctx => { var configStore = new ConfigurationStore (new TypeMapFactory(), MapperRegistry.AllMappers()); configStore.AddProfile (); return configStore; }) .AsImplementedInterfaces() .SingleInstance(); } }
这里有一些额外的代码来说明我如何在Global.asax中加载这些模块
static IContainerProvider _containerProvider; public IContainerProvider ContainerProvider { get { return _containerProvider; } } void Application_Start(object sender, EventArgs e) { RouteTable.Routes.MapHttpRoute( name: "ActionApi", routeTemplate: "api/{controller}/{action}" ); RouteTable.Routes.MapHttpRoute( name: "DefaultApi", routeTemplate: "api/{controller}/{id}", defaults: new { id = System.Web.Http.RouteParameter.Optional } ); var builder = new ContainerBuilder(); builder.RegisterModule(); builder.RegisterModule (); _containerProvider = new ContainerProvider(builder.Build()); }
错误:
AutoMapper.dll中出现"AutoMapper.AutoMapperMappingException"类型的异常,但未在用户代码中处理缺少类型映射配置或不支持的映射.\ r \n\r \nMapping类型:\ r \n用户 - > UserModel
我猜你遇到的问题是你正在注册两个ConfigurationStore
实例,但MappingEngine
只有一个作为构造函数参数.
当你在Autofac中注册多个东西时,它就是"最后的胜利".所以,当你解决一个MappingEngine
它会挑这样的构造:
public MappingEngine(IConfigurationProvider configurationProvider)
这只需要一个配置提供程序(ConfigurationStore
implements IConfigurationProvider
),所以你只能获得一个.这意味着它相当于:
container.Resolve<IConfigurationProvider>();
你只会得到一个.如果您需要解决所有这些问题,则需要解决IEnumerable<IConfigurationProvider>
来自Autofac的问题,例如:
container.Resolve<IEnumerable<IConfigurationProvider>>();
但这不会解决你的问题,它只描述了我认为正在发生的事情.
你需要做什么才能完成你想做的事情就是把事情搞得一团糟.不是ConfigurationStore
在每个模块中注册,而是仅注册配置文件.像这样(缩短了可读性):
public class CustomerDataModule : Autofac.Module { protected override void Load(ContainerBuilder builder) { builder.RegisterType<CustomerDataMapperProfile>().As<Profile>(); } } public class UserAuthenticationModule : Autofac.Module { protected override void Load(ContainerBuilder builder) { builder.RegisterType<UserAuthenticationMapperProfile>().As<Profile>(); } }
然后,您需要从模块中分解常见的AutoMapper注册.你不想双重注册.创建一个新模块,用于处理注册映射引擎,并对配置文件进行一些动态解析.
public class AutoMapperModule : Autofac.Module { protected override void Load(ContainerBuilder builder) { // Register the common thing once, not in each module. builder.RegisterType<MappingEngine>().As<IMappingEngine>(); // Here's where you dynamically get all the registered profiles // and add them at the same time to the config store. builder.Register(ctx => { var profiles = ctx.Resolve<IEnumerable<Profile>>(); var configStore = new ConfigurationStore (new TypeMapFactory(), MapperRegistry.AllMappers()); foreach(var profile in profiles) { configStore.AddProfile(profile); } return configStore; }) .AsImplementedInterfaces() .SingleInstance(); } }
确保注册容器中的所有模块:
var builder = new ContainerBuilder(); builder.RegisterModule<UserAuthenticationModule>(); builder.RegisterModule<CustomerDataModule>(); builder.RegisterModule<AutoMapperModule>(); _containerProvider = new ContainerProvider(builder.Build());
现在,您应该在解决时注册所有配置文件IMappingEngine
.