问题描述
我有几个接口(IMapFrom
和IMapTo
),可以简化我的AutoMapper
配置。每个接口都有MapTo
和MapFrom
方法的默认实现。我有一个单独的MappingProfile
类,该类使用反射来查找所有实现类,并调用其映射创建。
上述类如下:
public interface IMapFrom<T>
{
void MapFrom(Profile profile) => profile.CreateMap(typeof(T),GetType());
}
public interface IMapTo<T>
{
void MapTo(Profile profile) => profile.CreateMap(GetType(),typeof(T));
}
public class MappingProfile : Profile
{
public MappingProfile()
{
ApplyMappingsFromAssembly(Assembly.GetExecutingAssembly());
}
private void ApplyMappingsFromAssembly(Assembly assembly)
{
var types = assembly.GetExportedTypes()
.Where(t => t.GetInterfaces().Any(i =>
i.IsGenericType && (i.GetGenericTypeDefinition() == typeof(IMapFrom<>) ||
i.GetGenericTypeDefinition() == typeof(IMapTo<>))))
.ToList();
foreach (var type in types)
{
var instance = Activator.CreateInstance(type);
var mapTo = type.GetMethod("MapTo");
var mapFrom = type.GetMethod("MapFrom");
mapTo?.Invoke(instance,new object[] {this});
mapFrom?.Invoke(instance,new object[] {this});
}
}
}
如果实现接口的类覆盖了默认接口的实现,则MappingProfile
类将按需工作。但是,如果这些类仅依赖于默认实现,则mapTo
方法中的mapFrom
和ApplyMappingsFromAssembly
都为空。
例如,此类不会成功应用其映射:
public class CreateJobCommand :
UpdateJobInputModel,IMapFrom<UpdateJobInputModel>,IMapTo<Job>,IRequest<int>
{
}
如果没有在继承类中重新实现默认实现,我该如何获取?
解决方法
根据凯文·高斯(Kevin Gosse)对我的问题的评论,我考虑使用Microsoft documentation中的GetInterface().GetMethod()
。
如果我采用这种方法,那么现在可以运行的结果代码如下:
public class MappingProfile : Profile
{
public MappingProfile()
{
ApplyMappingsFromAssembly(Assembly.GetExecutingAssembly());
}
private void ApplyMappingsFromAssembly(Assembly assembly)
{
var types = assembly.GetExportedTypes()
.Where(t => t.GetInterfaces().Any(i =>
i.IsGenericType && (i.GetGenericTypeDefinition() == typeof(IMapFrom<>) ||
i.GetGenericTypeDefinition() == typeof(IMapTo<>))))
.ToList();
foreach (var type in types)
{
var instance = Activator.CreateInstance(type);
var mapTo = type.GetMethod("MapTo") ??
instance!.GetType()
.GetInterface("IMapTo`1")?
.GetMethod("MapTo");
var mapFrom = type.GetMethod("MapFrom") ??
instance!.GetType()
.GetInterface("IMapFrom`1")?
.GetMethod("MapFrom");
mapTo?.Invoke(instance,new object[] {this});
mapFrom?.Invoke(instance,new object[] {this});
}
}
}