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

上一篇: AutoMapper:给定类型的IValueFormatter的广泛使用

下一篇: 具有构造函数参数的AutoMapping对象