C# Autofac.Core.DependencyResolutionException使用自定义配置文件配置AutoMapper时
我正在使用Autofac 4.3、Autofac.Owin 4、Autofac.MVC5 4、Autofac.MVC5.Owin 4、Autofac.MVC5.Owin 4和AutoMapper 5.2配置AutoMapper,以将域对象从/映射到Asp.Net MVC5应用程序中的视图模型对象 我确实决定为每个域实体创建一个AutoMapper配置文件,如下图所示,只留下没有参数的构造函数,因为我想设置配置文件的名称 注意:此代码位于程序集A中C# Autofac.Core.DependencyResolutionException使用自定义配置文件配置AutoMapper时,c#,asp.net-mvc-5,owin,automapper,autofac,C#,Asp.net Mvc 5,Owin,Automapper,Autofac,我正在使用Autofac 4.3、Autofac.Owin 4、Autofac.MVC5 4、Autofac.MVC5.Owin 4、Autofac.MVC5.Owin 4和AutoMapper 5.2配置AutoMapper,以将域对象从/映射到Asp.Net MVC5应用程序中的视图模型对象 我确实决定为每个域实体创建一个AutoMapper配置文件,如下图所示,只留下没有参数的构造函数,因为我想设置配置文件的名称 注意:此代码位于程序集A中 public partial class Doc
public partial class DoctorsMappingProfile : Profile
{
#region Constructors
public DoctorsMappingProfile() : base(typeof(DoctorsMappingProfile).FullName)
{
// Code of mapping removed because it is not part of the problem
}
#endregion Constructors
}
为了注册AutoMapper和我遵循的配置文件,用户mpetito很好地解释了这些配置文件,并说明它们是按照用户检查的方式工作的。我在Startup分部类中的代码如下:
注1:此代码位于引用程序集A的程序集B中
public partial class DoctorsMappingProfile : Profile
{
#region Constructors
public DoctorsMappingProfile() : base(typeof(DoctorsMappingProfile).FullName)
{
// Code of mapping removed because it is not part of the problem
}
#endregion Constructors
}
注2:我对已注册的程序集执行程序集扫描,然后将扫描的程序集数组作为参数传递给ContainerBuilder的方法RegisterAssemblyTypes
public partial class Startup
{
#region Methods
public void ConfigureAutoFacContainer(IAppBuilder app)
{
var builder = new ContainerBuilder();
builder.RegisterControllers(typeof(MvcApplication).Assembly);
builder.RegisterFilterProvider();
builder.RegisterSource(new ViewRegistrationSource());
// TODO: Logger!
var assemblies = BuildManager.GetReferencedAssemblies().Cast<Assembly>().ToArray();
this.ConfigureAutoMapper(builder, assemblies);
// TODO: Modules!
var container = builder.Build();
DependencyResolver.SetResolver(new AutofacDependencyResolver(container));
app.UseAutofacMiddleware(container);
app.UseAutofacMvc();
}
private void ConfigureAutoMapper(ContainerBuilder builder, Assembly[] registeredAssemblies)
{
//register your profiles, or skip this if you don't want them in your container
builder.RegisterAssemblyTypes(registeredAssemblies).AssignableTo(typeof(Profile)).As<Profile>(); //.UsingConstructor(typeof(string));
//register your configuration as a single instance
builder.Register(ctx => new MapperConfiguration(cfg =>
{
//add your profiles (either resolve from container or however else you acquire them)
foreach (var profile in ctx.Resolve<IEnumerable<Profile>>())
{
cfg.AddProfile(profile);
}
})).AsSelf().SingleInstance();
//register your mapper
builder.Register(ctx => ctx.Resolve<MapperConfiguration>()
.CreateMapper(ctx.Resolve))
.As<IMapper>()
.InstancePerLifetimeScope();
}
#endregion Methods
}
注意:此代码位于程序集A中
public partial class DoctorsMappingProfile : G2AutoMapperProfile //Profile
{
#region Constructors
public DoctorsMappingProfile() : base(typeof(DoctorsMappingProfile).FullName)
{
//removed because it is not part of the problem
}
#endregion Constructors
}
最后,这是程序集B中的ConfigureAutoMapper代码,它可以工作:
private void ConfigureAutoMapper(ContainerBuilder builder, Assembly[] registeredAssemblies)
{
//register your profiles, or skip this if you don't want them in your container
builder.RegisterAssemblyTypes(registeredAssemblies).AssignableTo(typeof(G2AutoMapperProfile)).As<G2AutoMapperProfile>();
//register your configuration as a single instance
builder.Register(ctx => new MapperConfiguration(cfg =>
{
//add your profiles (either resolve from container or however else you acquire them)
foreach (var profile in ctx.Resolve<IEnumerable<G2AutoMapperProfile>>())
{
cfg.AddProfile(profile);
}
})).AsSelf().SingleInstance();
//register your mapper
builder.Register(ctx => ctx.Resolve<MapperConfiguration>()
.CreateMapper(ctx.Resolve))
.As<IMapper>()
.InstancePerLifetimeScope();
}
private void ConfigureAutoMapper(ContainerBuilder生成器,程序集[]注册表程序集)
{
//注册您的配置文件,如果您不想在容器中注册,请跳过此步骤
RegisterAssemblyTypes(registeredAssemblies).AssignableTo(typeof(G2AutoMapperProfile)).As();
//将配置注册为单个实例
builder.Register(ctx=>newmapperconfiguration(cfg=>
{
//添加您的配置文件(从容器解析或以其他方式获取)
foreach(ctx.Resolve()中的变量配置文件)
{
cfg.AddProfile(profile);
}
})).AsSelf().SingleInstance();
//注册你的地图绘制者
builder.Register(ctx=>ctx.Resolve()
.CreateMapper(ctx.Resolve))
.As()
.InstancePerLifetimeScope();
}
。。。但是我仍然不明白为什么原始代码对我不起作用。首先,您没有必要在
DoctorsMappingProfile
中显式调用Profile
的受保护构造函数。原因是您传递的profileName
是AutoMapper默认使用的,我们可以看到
另外,关于在Autofac容器中注册配置文件的第一种方法:
builder
.RegisterAssemblyTypes(注册表组件)
.可转让给(文件类型)
.As()
.使用构造函数(类型(字符串));
这意味着您明确要求Autofac使用构造函数创建概要文件
类的实例,该构造函数只有一个字符串类型的参数。问题是Autofac不知道它必须在构造函数中使用什么string
这也是错误的,因为您创建了一个无参数构造函数,该构造函数反过来调用参数化构造函数
我不确定使用无参数构造函数调用会有什么作用,但我认为,最好让Autofac为您选择最好的构造函数,尤其是当defaut参数较少的构造函数是您希望它使用的构造函数时
通过查看您提供的解决方案/解决方案,我的感觉得到了加强。你有效地做到了:
- 创建一个基类,该基类完全模仿
Profile
的特性,即默认的无参数构造函数和接受字符串的构造函数
- 通过不使用构造函数
在Autofac容器中注册配置文件
因此,我非常确定:
- 摆脱自定义基类
- 让您的配置文件再次从
Profile
继承
- 不使用构造函数注册您的配置文件
您应该很好。首先,您不需要在DoctorsMappingProfile
中显式调用Profile
的受保护构造函数。原因是您传递的profileName
是AutoMapper默认使用的,我们可以看到
另外,关于在Autofac容器中注册配置文件的第一种方法:
builder
.RegisterAssemblyTypes(注册表组件)
.可转让给(文件类型)
.As()
.使用构造函数(类型(字符串));
这意味着您明确要求Autofac使用构造函数创建概要文件
类的实例,该构造函数只有一个字符串类型的参数。问题是Autofac不知道它必须在构造函数中使用什么string
这也是错误的,因为您创建了一个无参数构造函数,该构造函数反过来调用参数化构造函数
我不确定使用无参数构造函数调用会有什么作用,但我认为,最好让Autofac为您选择最好的构造函数,尤其是当defaut参数较少的构造函数是您希望它使用的构造函数时
通过查看您提供的解决方案/解决方案,我的感觉得到了加强。你有效地做到了:
- 创建一个基类,该基类完全模仿
Profile
的特性,即默认的无参数构造函数和接受字符串的构造函数
- 通过不使用构造函数
在Autofac容器中注册配置文件
因此,我非常确定:
- 摆脱自定义基类
- 让您的配置文件再次从
Profile
继承
- 不使用构造函数注册您的配置文件
你应该没事。我为我的错误感到抱歉。我更正了粘贴在原始帖子中的代码。我描述的问题没有使用.UsingConstructor(t
public abstract class G2AutoMapperProfile : Profile
{
#region Constructors
protected G2AutoMapperProfile()
{
}
protected G2AutoMapperProfile(string profileName) : base(profileName)
{
}
#endregion Constructors
}
public partial class DoctorsMappingProfile : G2AutoMapperProfile //Profile
{
#region Constructors
public DoctorsMappingProfile() : base(typeof(DoctorsMappingProfile).FullName)
{
//removed because it is not part of the problem
}
#endregion Constructors
}
private void ConfigureAutoMapper(ContainerBuilder builder, Assembly[] registeredAssemblies)
{
//register your profiles, or skip this if you don't want them in your container
builder.RegisterAssemblyTypes(registeredAssemblies).AssignableTo(typeof(G2AutoMapperProfile)).As<G2AutoMapperProfile>();
//register your configuration as a single instance
builder.Register(ctx => new MapperConfiguration(cfg =>
{
//add your profiles (either resolve from container or however else you acquire them)
foreach (var profile in ctx.Resolve<IEnumerable<G2AutoMapperProfile>>())
{
cfg.AddProfile(profile);
}
})).AsSelf().SingleInstance();
//register your mapper
builder.Register(ctx => ctx.Resolve<MapperConfiguration>()
.CreateMapper(ctx.Resolve))
.As<IMapper>()
.InstancePerLifetimeScope();
}