Uthman Rahimi
Uthman Rahimi

Reputation: 708

how to generic Automapper Config

I use Automapper version 4.2.0 and I all Action Methods I have setting Like this :

  var attributeGroups = _attributeGroupService.AttributeGroupDropdown();
        var mapconfiguration = new MapperConfiguration(cfg => cfg.CreateMap<AttributeGroup, AttributeGroupViewModel>());
        var mapper = mapconfiguration.CreateMapper();
        var result = mapper.Map(attributeGroups, new List<AttributeGroupViewModel>());

I dont repeat this codes in all actions , I want create a generic method and just pass data to it and map it ,to do this , I create a Method like this ?

 public N mapping<T,K,M,N>(T resource, K destination,M model,N newModel) 
    {
        var mapconfiguration = new MapperConfiguration(cfg => cfg.CreateMap<T, K>());
        var mapper = mapconfiguration.CreateMapper();
        var result = mapper.Map<M,N>(model, newModel);
        return result;
    }

and call it like this :

var ResultTest=mapping<AttributeGroup,AttributeGroupViewModel,attributeGroups,new List<AttributeGroupViewModel>()>();

but it doesnt complie .

how can I do it?

Upvotes: 1

Views: 1146

Answers (1)

grek40
grek40

Reputation: 13438

Short answer: you need to provide types in the generic parameter list and variables in the argument list of your function call. Also, you don't need the T resource, K destination arguments at all, since they are unused.

There is another problem with your approach, since using it is not really convenient. So I suggest that you provide two specialized methods with reduced complexity.

See the below complete example. It contains the method mapAnything<...>, which is a working equivalent to your mapping<...> method. The methods mapObject<...> and mapCollection<...> are the specialized methods I was talking about.

class TestResource
{
    public int Testnumber { get; set; }
    public string Testtext { get; set; }
}

class TestDestination
{
    public string Testtext { get; set; }
}

class Program
{
    // equivalent to what you tried to do - needs explicit generic parameters on call
    static N mapAnything<T, K, M, N>(M model, N newModel)
    {
        var mapconfiguration = new MapperConfiguration(cfg => cfg.CreateMap<T, K>());
        var mapper = mapconfiguration.CreateMapper();
        var result = mapper.Map<M, N>(model, newModel);
        return result;
    }

    // variant for object mapping, where generics can be implicitely inferred
    static N mapObject<M, N>(M model, N newModel)
    {
        var mapconfiguration = new MapperConfiguration(cfg => cfg.CreateMap<M, N>());
        var mapper = mapconfiguration.CreateMapper();
        var result = mapper.Map<M, N>(model, newModel);
        return result;
    }

    // variant for lists, where generics can be implicitely inferred
    static ICollection<N> mapCollection<M, N>(IEnumerable<M> model, ICollection<N> newModel)
    {
        var mapconfiguration = new MapperConfiguration(cfg => cfg.CreateMap<M, N>());
        var mapper = mapconfiguration.CreateMapper();
        var result = mapper.Map<IEnumerable<M>, ICollection<N>>(model, newModel);
        return result;
    }

    static void Main(string[] args)
    {
        var res1 = new TestResource() { Testnumber = 1, Testtext = "a" };
        var res2 = new List<TestResource>();
        for (int i = 0; i < 10; i++)
        {
            res2.Add(new TestResource() { Testnumber = i, Testtext = "test: " + i });
        }
        var mapped1 = mapObject(res1, new TestDestination());
        var mapped2 = mapCollection(res2, new HashSet<TestDestination>());
        var mapped3 = mapAnything<TestResource, TestDestination, TestResource, TestDestination>(res1, new TestDestination());
        var mapped4 = mapAnything<TestResource, TestDestination, IEnumerable<TestResource>, List<TestDestination>>(res2, new List<TestDestination>());
    }
}

Upvotes: 2

Related Questions