【问题标题】:Exception when I try to combine Autofac with AutoMapper`s IMappingEngine当我尝试将 Autofac 与 AutoMapper 的 IMappingEngine 结合使用时出现异常
【发布时间】:2015-09-28 01:04:23
【问题描述】:

这就是我的 DI 和 Automapper 设置:

[RoutePrefix("api/productdetails")]
public class ProductController : ApiController
{
    private readonly IProductRepository _repository;
    private readonly IMappingEngine _mappingEngine;

    public ProductController(IProductRepository repository, IMappingEngine mappingEngine)
    {
        _repository = repository;
        _mappingEngine = mappingEngine;
    }
}

public class WebApiApplication : System.Web.HttpApplication
{
    protected void Application_Start()
    {
        GlobalConfiguration.Configure(WebApiConfig.Register);

        //WebApiConfig.Register(GlobalConfiguration.Configuration);          
        RouteConfig.RegisterRoutes(RouteTable.Routes);          
    }
}


public static class WebApiConfig
{
    public static void Register(HttpConfiguration config)
    {
        config.MapHttpAttributeRoutes();
        config.Routes.MapHttpRoute("DefaultApi", "api/{controller}/{id}", new { id = RouteParameter.Optional });

        // Filter
        config.Filters.Add(new ActionExceptionFilter());
        config.Services.Replace(typeof(IExceptionHandler), new GlobalExceptionHandler());


        // DI
        // Register services
        var builder = new ContainerBuilder();
        builder.RegisterType<ProductRepository>().As<IProductRepository>().InstancePerRequest();
        builder.RegisterType<MappingEngine>().As<IMappingEngine>();

        // AutoMapper
        RegisterAutoMapper(builder);

        // FluentValidation

        // do that finally!
        // This is need that AutoFac works with controller type injection
        builder.RegisterApiControllers(Assembly.GetExecutingAssembly());
        var container = builder.Build();
        config.DependencyResolver = new AutofacWebApiDependencyResolver(container);
    }

    private static void RegisterAutoMapper(ContainerBuilder builder)
    {
        var profiles =
            AppDomain.CurrentDomain.GetAssemblies()
                .SelectMany(GetLoadableTypes)
                .Where(t => t != typeof (Profile) && typeof (Profile).IsAssignableFrom(t));
        foreach (var profile in profiles)
        {
            Mapper.Configuration.AddProfile((Profile) Activator.CreateInstance(profile));
        }

    }

    private static IEnumerable<Type> GetLoadableTypes(Assembly assembly)
    {
        try
        {
            return assembly.GetTypes();
        }
        catch (ReflectionTypeLoadException e)
        {
            return e.Types.Where(t => t != null);
        }
    }
}

这是我去某条路线时遇到的异常:

None of the constructors found with 'Autofac.Core.Activators.Reflection.DefaultConstructorFinder' on type 'AutoMapper.MappingEngine' can be invoked with the available services and parameters:
Cannot resolve parameter 'AutoMapper.IConfigurationProvider configurationProvider' of constructor 'Void .ctor(AutoMapper.IConfigurationProvider)'.
Cannot resolve parameter 'AutoMapper.IConfigurationProvider configurationProvider' of constructor 'Void .ctor(AutoMapper.IConfigurationProvider, AutoMapper.Internal.IDictionary`2[AutoMapper.Impl.TypePair,AutoMapper.IObjectMapper], System.Func`2[System.Type,System.Object])'.

问题

我的代码有什么问题?

【问题讨论】:

  • 顺便说一句,我不建议将 IMappingEngine 作为依赖项。就用真品吧。
  • 是的,当我将配置文件添加到 Mapper.xxx 时,Mapper 似乎加载了配置文件,但 imappingEngine 没有配置文件我得到一个例外......所以你建议直接使用 Mapper.Map在控制器中?
  • 是的,我个人还没有看到需要注入 AutoMapper

标签: c# asp.net-web-api automapper asp.net-web-api2 autofac


【解决方案1】:

错误来自这一行:

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

这一行告诉 Autofac 在您需要 IMappingEngine 时实例化 MappingEngine。如果你查看MappingEngine 的可用构造函数,你会发现 Autofac 不能使用它们中的任何一个,因为它不能注入所需的参数。

这里是MappingEngine的可用构造函数

public MappingEngine(IConfigurationProvider configurationProvider)
public MappingEngine(IConfigurationProvider configurationProvider, 
                     IDictionary<TypePair, IObjectMapper> objectMapperCache, 
                     Func<Type, object> serviceCtor)

解决此问题的解决方案之一是告诉 Autofac 如何创建您的MappingEngine,您可以使用委托注册来完成。

builder.Register(c => new MappingEngine(...)).As<IMappingEngine>();

你也可以注册一个IConfigurationProvider,这样Autofac就能自动找到好的构造函数了。

解决此问题的最简单方法是在 Autofac 中注册 IConfigurationProvider

builder.Register(c => new ConfigurationStore(new TypeMapFactory(), MapperRegistry.Mappers))
       .As<IConfigurationProvider>()
       .SingleInstance();
builder.RegisterType<MappingEngine>()
       .As<IMappingEngine>();

您还可以在此处找到更多信息:AutoMapper, Autofac, Web API, and Per-Request Dependency Lifetime Scopes

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2022-12-16
    • 2016-06-24
    • 2012-11-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-03-29
    相关资源
    最近更新 更多