无法在Autofac中注册并添加automapper配置文件

raj*_*111 1 c# asp.net inversion-of-control autofac automapper

我有一个多租户Web应用程序,它有多个模块.我使用autofac作为IOC和Automapper来映射我的模型和实体.在下面的代码中,我能够将UserAuthenticationMapper配置文件添加到automapper,但无法添加CustomerDataMapper配置文件.Autofac仅向自动化MappingEngine添加一个映射器配置文件,并忽略其余部分.我在做什么错了?

这是我的UserAuthentication模块:

 public class UserAuthenticationModule: Autofac.Module
 {
    protected override void Load(ContainerBuilder builder)
    {
        builder.RegisterType<MappingEngine>().As<IMappingEngine>();

        builder.Register(ctx =>
        {
            var configStore = new ConfigurationStore
           (new TypeMapFactory(),  MapperRegistry.AllMappers());
            configStore.AddProfile<UserAuthenticationMapperProfile>();
            return configStore;
        })
        .AsImplementedInterfaces()
        .SingleInstance();

        var assembly = Assembly.GetExecutingAssembly();
        builder.RegisterAssemblyTypes(assembly)
               .Where(t => t.Name.EndsWith("Service"))
               .AsImplementedInterfaces()
               .SingleInstance();
      }
  }
Run Code Online (Sandbox Code Playgroud)

CustomerData Modue:

  public class CustomerDataModule : Autofac.Module
  {
    protected override void Load(ContainerBuilder builder)
    {
        builder.RegisterType<CustomerDataService>()
            .As<ICustomerDataService>()
            .InstancePerDependency();

        builder.RegisterType<MappingEngine>().As<IMappingEngine>();

        builder.Register(ctx =>
            {
                var configStore = new ConfigurationStore
                (new TypeMapFactory(), MapperRegistry.AllMappers());
                configStore.AddProfile<CustomerDataMapperProfile>();
                return configStore;
            })
               .AsImplementedInterfaces()
               .SingleInstance();
      }
   }
Run Code Online (Sandbox Code Playgroud)

这里有一些额外的代码来说明我如何在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<UserAuthenticationModule>();
      builder.RegisterModule<CustomerDataModule>();
      _containerProvider = new ContainerProvider(builder.Build());
     }
Run Code Online (Sandbox Code Playgroud)

错误:

AutoMapper.dll中出现"AutoMapper.AutoMapperMappingException"类型的异常,但未在用户代码中处理缺少类型映射配置或不支持的映射.\ r \n\r \nMapping类型:\ r \n用户 - > UserModel

Tra*_*lig 6

我猜你遇到的问题是你正在注册两个ConfigurationStore实例,MappingEngine只有一个作为构造函数参数.

当你在Autofac中注册多个东西时,它就是"最后的胜利".所以,当你解决一个MappingEngine它会挑这样的构造:

public MappingEngine(IConfigurationProvider configurationProvider)
Run Code Online (Sandbox Code Playgroud)

这只需要一个配置提供程序(ConfigurationStoreimplements IConfigurationProvider),所以你只能获得一个.这意味着它相当于:

container.Resolve<IConfigurationProvider>();
Run Code Online (Sandbox Code Playgroud)

你只会得到一个.如果您需要解决所有这些问题,则需要解决IEnumerable<IConfigurationProvider>来自Autofac的问题,例如:

container.Resolve<IEnumerable<IConfigurationProvider>>();
Run Code Online (Sandbox Code Playgroud)

但这不会解决你的问题,它只描述了我认为正在发生的事情.

你需要做什么才能完成你想做的事情就是把事情搞得一团糟.不是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>();
  }
}
Run Code Online (Sandbox Code Playgroud)

然后,您需要从模块中分解常见的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();
  }
}
Run Code Online (Sandbox Code Playgroud)

确保注册容器中的所有模块:

 var builder = new ContainerBuilder();
 builder.RegisterModule<UserAuthenticationModule>();
 builder.RegisterModule<CustomerDataModule>();
 builder.RegisterModule<AutoMapperModule>();
 _containerProvider = new ContainerProvider(builder.Build());
Run Code Online (Sandbox Code Playgroud)

现在,您应该在解决时注册所有配置文件IMappingEngine.