AutoMapping Object with Constructor Arguments
I am trying to configure AutoMapper to work with a class which requires a constructor argument. I've done quite a bit of online research into this, and found several examples...but they either don't use instance-based AutoMapper, or they are for older versions of AutoMapper.
I'm using AutoMapper to deep clone objects. Here's the profile I've created:
public class ScannerAutoMapProfile : Profile
{
public ScannerAutoMapProfile()
{
CreateMap<AzureConfiguration>();
CreateMap<CommunityUser>();
CreateMap<Community>();
CreateMap<Contact>();
CreateMap<DatabaseConnection>();
CreateMap<DatabaseConfiguration>();
CreateMap<LoginManagement>();
CreateMap<MaxLoadSeconds>();
CreateMap<ScanTime>();
CreateMap<ScanningAcceleration>();
CreateMap<ScanningWindow>();
CreateMap<ScanningInterval>();
CreateMap<Scanning>();
CreateMap<SearchParameterUser>();
CreateMap<SearchParameter>();
CreateMap<ScannerConfiguration>();
}
private void CreateMap<TModel>()
{
CreateMap<TModel, TModel>();
}
}
The problem is occurring with ScannerConfiguration, which takes a single string parameter.
Here's the Autofac module I'm using:
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 =>
{
foreach( var profile in c.Resolve<IEnumerable<Profile>>() )
{
cfg.AddProfile( profile );
}
} ) )
.AsSelf()
.SingleInstance();
builder.Register( c => c.Resolve<MapperConfiguration>().CreateMapper( c.Resolve ) )
.As<IMapper>()
.SingleInstance();
}
}
(thanx to http://www.protomatter.co.uk/blog/development/2017/02/modular-automapper-registrations-with-autofac/ for this).
I can successfully instantiate an IMapper, which shows the Autofac stuff is working properly. But when I attempt to call Map:
_onDisk = Mapper.Map<ScannerConfiguration>( _inMemory );
it fails with a "ScannerConfiguration has no parameterless constructor" exception.
Unfortunately, while I'm pretty sure I need to provide some options to that Map() call, I haven't been able to figure out how to do it. The parameter I need to pass in to the constructor is a public property of ScannerConfiguration, called SourceFilePath.
由于ScannerConfiguration
需要一个参数,为什么不自己初始化它?
var sc = new ScannerConfiguration("some string value");
_onDisk = Mapper.Map( _inMemory, sc );
If Automapper can't create an instance of the destination using a default constructor, you can give Automapper a function that calls a constructor and returns the new instance with ConstructUsing
. After it constructs the object it continues mapping as usual.
For example here's a source and destination class. The destination class can't be created without calling a non-default constructor:
public class SourceClass
{
public string SourceStringProperty { get; set; }
public int OtherSourceProperty { get; set; }
public bool SameNameInBoth { get; set; }
}
public class DestinationClass
{
public DestinationClass(string destinationString)
{
DestinationStringPropertyFromConstructor = destinationString;
}
public string DestinationStringPropertyFromConstructor { get; }
public int OtherDestinationProperty { get; set; }
public bool SameNameInBoth { get; set; }
}
The mapping would look like this:
Mapper.Initialize(cfg =>
{
cfg.CreateMap<SourceClass, DestinationClass>()
.ConstructUsing(hasString => new DestinationClass(hasString.SourceStringProperty))
.ForMember(dest => dest.OtherDestinationProperty,
opt => opt.MapFrom(src => src.OtherSourceProperty));
});
I added the other properties just to demonstrate that other than specifying a constructor, the other configuration details are all the same.
链接地址: http://www.djcxy.com/p/37406.html