当我尝试将Autofac与AutoMapper的IMappingEngine结合使用时出现异常

时间:2015-07-09 14:55:26

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

这就是我的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])'.

问题

我的代码出了什么问题?

1 个答案:

答案 0 :(得分:1)

错误来自这一行:

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

当您需要MappingEngine时,此行告诉 Autofac 设置IMappingEngine。如果您查看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