I want to map my objects with generic extension methods.
public class Customer
{
public string FirstName { get; set; }
public string LastName { get; set; }
public string Email { get; set; }
public Address HomeAddress { get; set; }
public string GetFullName()
{
return string.Format(“{0} {1}”, FirstName, LastName);
}
}
And this is viewmodel
public class CustomerListViewModel
{
public string FullName { get; set; }
public string Email { get; set; }
public string HomeAddressCountry { get; set; }
}
So I am creating map, Mapper.CreateMap<Customer, CustomerListViewModel>();
And I want to create an extension method
public static class MapperHelper
{
public static CustomerListViewModel ToViewModel(this Customer cust)
{
return AutoMapper.Mapper.Map<Customer, CustomerListViewModel>(cust);
}
}
But I want to make generic this helper:
public static class MapperHelper<TSource, TDest>
{
public static TDest ToViewModel(this TSource cust)
{
return AutoMapper.Mapper.Map<TSource, TDest>(cust);
}
}
Gives error: Extension method can only be declared in non-generic, non-nested static class
If I can not make generic, I should create helper class for all mapping. Is there any way to solution?
CreateMapExpression in AutoMapper creates an expression for mapping between Source to Destination. In the next line we use the mapper expression and pass this to Compose extension method to build a new expression. And finally we call Where method on Users DBSet and it returns IQueriable of type Destination.
The built-in enum mapper is not configurable, it can only be replaced. Alternatively, AutoMapper supports convention based mapping of enum values in a separate package AutoMapper.Extensions.EnumMapping. For method CreateMap this library provide a ConvertUsingEnumMapping method.
Now, the real issue is when we want to implement Find method which accepts Expression<Func<Source, bool. Mapping an expression of func of type source to expression of func of type destination is more difficult as Jimmy Bogard main author of Automapper stated in this mailing list.
AutoMapper extentions for mapping expressions (OData) To use, configure using the configuration helper method: var mapper = new Mapper (new MapperConfiguration (cfg => { cfg. AddExpressionMapping (); // Rest of your configuration })); // or if using the MS Ext DI: services.
Even better than these solutions is to use the non-generic Map method:
public static class MapperHelper
{
public static TDest MapTo<TDest>(this object src)
{
return (TDest)AutoMapper.Mapper.Map(src, src.GetType(), typeof(TDest));
}
}
In your code:
var model = customter.MapTo<CustomerViewModel>();
Now you don't need the superfluous Source type in your generic method.
Can't you just do this?:
public static class MapperHelper
{
public static TDest ToViewModel<TSource, TDest>(this TSource cust)
{
return AutoMapper.Mapper.Map<TSource, TDest>(cust);
}
}
You can't define extension methods in a generic class because there would be no way for you to specify the type parameters when you invoke it!
public static class MapperHelper<TSource, TTarget>
{
public static TTarget ToViewModel(this TSource source)
{
...
}
}
...
// this is no problem if we invoke our method like a
// static method:-
var viewModel = MapperHelper<MyModel, MyViewModel>.ToViewModel(model);
// but if we use the extension method syntax then how
// does the compiler know what TSource and TTarget are?:-
var viewModel = model.ToViewModel();
You have to make the method generic instead:-
public static class MapperHelper
{
public static TTarget ToViewModel<TSource, TTarget>(this TSource source)
{
...
}
}
...
var viewModel = model.ToViewModel<MyModel, MyViewModel>();
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With