简体   繁体   中英

Is it possible for Automapper to map fields to concrete classes

I have a interface, with two classes that inherit from it.

public interface IField
{
    int FieldID { get; set; }
    string FieldName { get; set; }
    string FieldType { get; }
    string FieldDisplayValue { get; set; }
}

public abstract class BaseField : IField
{
    public int FieldID { get; set; }
    public string FieldName { get; set; }
    public abstract string FieldType { get; }
    public string FieldDisplayValue { get; set; }
}

public class StaticText : BaseField, IField
{
    public override string FieldType => "Text";
}

public class TextField : BaseField, IField
{
    public override string FieldType => "TextBox";
    public bool Required { get; set; }
    public int MinimumLength { get; set; }
    public int MaximumLength { get; set; }
    public string DefaultText { get; set; }
}

I would like to automap a generic class to one of these classes, based on a type included in the incoming class.

public class FieldViewModel
{
    public int FieldID { get; set; }
    public string FieldName { get; set; }
    public  string FieldType { get; set;  }
    public string FieldDisplayValue { get; set; }
    public bool Required { get; set; }
    public int MinimumLength { get; set; }
    public int MaximumLength { get; set; }
    public string DefaultText { get; set; }

}

I have constructed a factory class that will return the appropriate object based on the fieldType. I have successfully gotten automapper to use the factory to create the correct concrete class, but it will only map fields from the interface, not any of the extra fields defined in the concrete classes.

my map for the interface to concrete classes looks like this:

cfg.CreateMap<FieldViewModel, IField>()
                .ConstructUsing(x => FieldFactory.CreateField(x.FieldType));

var iMapper = config.CreateMapper();

var field = iMapper.Map<FieldViewModel, IField>(sourceObject);

when passing in a source class that contains required, minimum, or maximum, those fields are not being mapped in the newly created concrete class.

Is this even possible to do with automapper? or do I need to map these fields myself?

after a bit more research, it looks like what I was missing was the beforeMap code.

cfg.CreateMap<FieldViewModel, IField>()
                .ConstructUsing(x => FieldFactory.CreateField(x.FieldType))
                .BeforeMap((s,d,c) => c.Mapper.Map(s, d));
            cfg.CreateMap<FieldViewModel, StaticText>();
            cfg.CreateMap<FieldViewModel, TextField>();

ended up having to create map for each derived concrete class, but the before map handles making sure the right one gets mapped with data.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM