Marc
Marc

Reputation: 16512

How to ignore properties based on their type

I'm using AutoMapper to copy an entity framework object to another identical database. The problem is that it tries to copy the lookup tables.

I have tried to exclude them with the AddGlobalIgnore and the ShouldMapProperty but it doesn't work. AutoMapper still try to copy those properties.

Here's my code. I would like to ignore the properties that start with "LU"

 dynamic newObject= new NewObject();

 MapperConfiguration config = new MapperConfiguration(cfg =>
 {
     cfg.CreateMissingTypeMaps = true;
     cfg.AddGlobalIgnore("LU");
     cfg.ShouldMapProperty = p => !p.GetType().ToString().StartsWith("LU");
     cfg.ShouldMapField = p => !p.GetType().ToString().StartsWith("LU");
 });
 IMapper mapper = config.CreateMapper();
 newObject = mapper.Map(objectToCopy, objectToCopy.GetType(), newObject.GetType()); 

I did also tried

MapperConfiguration config = new MapperConfiguration(cfg =>
{
   cfg.CreateMissingTypeMaps = true;
   cfg.AddGlobalIgnore("LU");
   cfg.ShouldMapProperty = p => !p.PropertyType.Name.StartsWith("LU");
   cfg.ShouldMapField = p => !p.FieldType.Name.StartsWith("LU");
 });

and

MapperConfiguration config = new MapperConfiguration(cfg =>
{
   cfg.CreateMissingTypeMaps = true;
   cfg.AddGlobalIgnore("LU");
   cfg.ShouldMapProperty = p => !p.Name.StartsWith("LU");
   cfg.ShouldMapField = p => !p.Name.StartsWith("LU");
});

Upvotes: 6

Views: 1537

Answers (2)

Will Ray
Will Ray

Reputation: 10879

Create your configuration as a separate profile, then add that profile to the mapper configuration.

class Program
{
    static void Main(string[] args)
    {
        dynamic newObject = new NewObject();
        var objectToCopy = new ObjectToCopy();

        var config = new MapperConfiguration(cfg =>
        {
            cfg.AddProfile<MyProfile>();
        });

        var mapper = config.CreateMapper();
        mapper.Map(objectToCopy, newObject);
        // newObject.LU_Ignore = "Original value"
        // newObject.DoNotIgnore = "New value"
    }
}

class MyProfile : Profile
{
    protected override void Configure()
    {
        CreateMissingTypeMaps = true;
        ShouldMapProperty = p => !p.Name.StartsWith("LU"); // this is the correct way to get the property name
    }
}

class ObjectToCopy
{
    public string LU_Ignore { get; set; } = "New value";

    public string DoNotIgnore { get; set; } = "New value";
}


class NewObject
{
    public string LU_Ignore { get; set; } = "Original value";

    public string DoNotIgnore { get; set; } = "Original value";
}

Something seems goofy about how configurations are applied to the Mapper created form the mapper.CreateMapper call. I'm looking into it to see if I can find out more information and will update this answer if I find anything.

Upvotes: 4

Tamas Ionut
Tamas Ionut

Reputation: 4410

I wont say that this is the best (performant or design-wise) approach, but this works:

public static class AutoExtensions {
    public static IMappingExpression Ignore(this IMappingExpression expression, Func<PropertyInfo, bool> filter) {
        foreach (var propertyName in expression
            .TypeMap
            .SourceType
            .GetProperties()
            .Where(filter)
            .Select(x=>x.Name))
        {
            expression.ForMember(propertyName, behaviour => behaviour.Ignore());
        }

        return expression;
    }
}

You can configure your mapper like this (for these sample classes):

public class Client {
    public string LUName { get; set; }
    public string Dno { get; set; } 
}

public class ClientDTO
{
    public string LUName { get; set; }
    public string Dno { get; set; } 
}

and test it out like this:

private static void ConfigAndTestMapper() {
        var config = new MapperConfiguration(cfg =>{
            cfg.CreateMap(typeof (Client), typeof (ClientDTO))
                .Ignore(x => x.Name.StartsWith("LU"));
        });

        var mapper = config.CreateMapper();
        var result = mapper.Map<ClientDTO>(new Client() {LUName = "Name", Dno = "Dno"});

        var isIgnored = result.LUName == null;
    }

PS: this is also pretty "hackish" since it tries to map all kind of properties there (readonly/non-public, etc.) so take it with a grain of salt.

Upvotes: 0

Related Questions