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

时间:2013-12-05 21:32:06

标签: c# asp.net inversion-of-control automapper autofac

我有一个多租户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();
      }
  }

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();
      }
   }

这里有一些额外的代码来展示我如何在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());
     }

错误:

AutoMapper.dll中出现“AutoMapper.AutoMapperMappingException”类型的异常,但未在用户代码中处理 缺少类型映射配置或不支持的映射。\ r \ n \ r \ n映射类型:\ r \ n用户 - &gt;的usermodel

1 个答案:

答案 0 :(得分:6)

我猜你遇到的问题是你正在注册两个ConfigurationStore个实例 MappingEngine只需要一个构造函数参数。

当您在Autofac中注册多个内容时,它会“获胜”。所以当你解决a MappingEngine时,它会选择这样的构造函数:

public MappingEngine(IConfigurationProvider configurationProvider)

这只需要一个配置提供程序(ConfigurationStore实现IConfigurationProvider),因此您只能获得一个。这意味着它相当于:

container.Resolve<IConfigurationProvider>();

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

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时注册所有配置文件。