这就是我的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])'.
问题
我的代码出了什么问题?
答案 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