当我尝试将 Autofac 与 AutoMapper 的 IMappingEngine 结合使用时出现异常
Exception when I try to combine Autofac with AutoMapper`s IMappingEngine
这就是我的 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])'.
问题
我的代码有什么问题?
错误来自这一行:
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
这就是我的 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])'.
问题
我的代码有什么问题?
错误来自这一行:
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