【发布时间】:2018-10-20 05:09:30
【问题描述】:
我对 Autofac 可以在多大程度上与 Automapper 一起使用来映射对象感到困惑。我在网上阅读了很多关于集成这两个包的材料,但几乎所有的似乎都关注如何从 Automapper Profiles 创建 IMapper 的实例,使用类似这样的代码,它定义了一个 Autofac 模块(CSContainer.Instance 是一个Autofac 的 IContainer 的静态实例):
public class AutoMapperModule : Module
{
private static object ServiceConstructor( Type type )
{
return CSContainer.Instance.Resolve( type );
}
protected override void Load( ContainerBuilder builder )
{
base.Load( builder );
var assemblies = AppDomain.CurrentDomain.GetAssemblies();
builder.RegisterAssemblyTypes( assemblies )
.Where( t => typeof(Profile).IsAssignableFrom( t ) && !t.IsAbstract && t.IsPublic )
.As<Profile>();
builder.Register( c => new MapperConfiguration( cfg =>
{
cfg.ConstructServicesUsing( ServiceConstructor );
foreach( var profile in c.Resolve<IEnumerable<Profile>>() )
{
cfg.AddProfile( profile );
}
} ) )
.AsSelf()
.AutoActivate()
.SingleInstance();
builder.Register( c => c.Resolve<MapperConfiguration>().CreateMapper( c.Resolve ) )
.As<IMapper>()
.SingleInstance();
}
}
(有关此方法的说明,请参阅 http://www.protomatter.co.uk/blog/development/2017/02/modular-automapper-registrations-with-autofac/)
我想做的是让 Automapper 调用 Autofac 来创建对象。现在我能看到的唯一方法是做这样的事情:
创建地图() .ConstructUsing(src => CSContainer.Instance.Resolve());
这行得通,但感觉很笨拙。如果 Automapper 尝试发现如何使用 Autofac 自动解析实例,就像在幕后一样。
我认为这样的事情可能会奏效(这是我上面引用的第一个 Autofac 模块的修改版本):
public class AutoMapperModule : Module
{
protected override void Load( ContainerBuilder builder )
{
base.Load( builder );
var assemblies = AppDomain.CurrentDomain.GetAssemblies();
builder.RegisterAssemblyTypes( assemblies )
.Where( t => typeof(Profile).IsAssignableFrom( t ) && !t.IsAbstract && t.IsPublic )
.As<Profile>();
builder.Register( c => new MapperConfiguration( cfg =>
{
cfg.ForAllMaps( ( map, opts ) =>
opts.ConstructUsing( ( x, y ) => CSContainer.Instance.Resolve(map.DestinationType) ) );
foreach( var profile in c.Resolve<IEnumerable<Profile>>() )
{
cfg.AddProfile( profile );
}
} ) )
.AsSelf()
.AutoActivate()
.SingleInstance();
builder.Register( c => c.Resolve<MapperConfiguration>().CreateMapper( c.Resolve ) )
.As<IMapper>()
.SingleInstance();
}
但这导致 Autofac 抛出异常,抱怨我试图重用已经定义的构建器(抱歉,我手边没有确切的措辞)。
是否可以集成 Automapper 和 Autofac,以便 Automapper 通过 Autofac 解析新实例?如果是这样,最好的方法是什么?
其他信息
所以我按照以下方式实现了建议的答案:
protected override void Load( ContainerBuilder builder )
{
base.Load( builder );
var assemblies = AppDomain.CurrentDomain.GetAssemblies();
builder.RegisterAssemblyTypes( assemblies )
.Where( t => typeof(Profile).IsAssignableFrom( t ) && !t.IsAbstract && t.IsPublic )
.As<Profile>();
builder.Register( c => new MapperConfiguration( cfg =>
{
cfg.ConstructServicesUsing( ServiceConstructor );
foreach( var profile in c.Resolve<IEnumerable<Profile>>() )
{
cfg.AddProfile( profile );
}
} ) )
.AsSelf()
.AutoActivate()
.SingleInstance();
builder.Register( c =>
{
// these are the changed lines
var scope = c.Resolve<ILifetimeScope>();
return new Mapper(c.Resolve<MapperConfiguration>(), scope.Resolve );
} )
.As<IMapper>()
.SingleInstance();
}
但这会导致 Automapper 异常,抱怨我试图通过调用 Map() 创建的对象必须有零参数,或者只有可选参数。然而,所有对象的构造函数参数也都在 Autofac 中注册,并且在我的代码中的其他地方自行创建对象实例没有问题。只是当 Automapper 尝试创建一个实例时,事情就变得混乱了。
【问题讨论】:
标签: automapper autofac