C# 自动映射自动创建createMap
我有一个服务正在调用另一个服务。这两个服务都使用“相同的类”。这些类的名称相同,属性相同,但名称空间不同,因此我需要使用AutoMapper从一个类型映射到另一个类型 不,这很简单,因为我所要做的就是C# 自动映射自动创建createMap,c#,automapper,C#,Automapper,我有一个服务正在调用另一个服务。这两个服务都使用“相同的类”。这些类的名称相同,属性相同,但名称空间不同,因此我需要使用AutoMapper从一个类型映射到另一个类型 不,这很简单,因为我所要做的就是CreateMap,但问题是我们有大约数百个类,我需要手动从中编写CreateMap,它的工作与我有关。没有任何自动CreateMap功能。因此,如果我说CreateMap(),那么AutoMaper将通过组织工作并找到所有类,并自动为这些类及其子类执行CreateMap 希望有一个简单的解决方案,
CreateMap
,但问题是我们有大约数百个类,我需要手动从中编写CreateMap
,它的工作与我有关。没有任何自动CreateMap
功能。因此,如果我说CreateMap(),那么AutoMaper将通过组织工作并找到所有类,并自动为这些类及其子类执行CreateMap
希望有一个简单的解决方案,或者我想一些反射可以解决它…AutoMapper有一个DynamicMap方法,您可以使用它:下面是一个示例单元测试来说明它
[TestClass]
public class AutoMapper_Example
{
[TestMethod]
public void AutoMapper_DynamicMap()
{
Source source = new Source {Id = 1, Name = "Mr FooBar"};
Target target = Mapper.DynamicMap<Target>(source);
Assert.AreEqual(1, target.Id);
Assert.AreEqual("Mr FooBar", target.Name);
}
private class Target
{
public int Id { get; set; }
public string Name { get; set; }
}
private class Source
{
public int Id { get; set; }
public string Name { get; set; }
}
}
[TestClass]
公共类AutoMapper_示例
{
[测试方法]
public void AutoMapper_DynamicMap()
{
Source Source=newsource{Id=1,Name=“Mr FooBar”};
Target=Mapper.DynamicMap(源);
arest.AreEqual(1,target.Id);
Assert.AreEqual(“Mr FooBar”,target.Name);
}
私有类目标
{
公共int Id{get;set;}
公共字符串名称{get;set;}
}
私有类源
{
公共int Id{get;set;}
公共字符串名称{get;set;}
}
}
只需在选项中将CreateMissingTypeMaps
设置为true:
var dto = Mapper.Map<FooDTO>
(foo, opts => opts.CreateMissingTypeMaps = true);
如果要继续使用旧的静态API(不再推荐),也可以执行以下操作:
Mapper.Initialize(cfg =>
{
cfg.CreateMissingTypeMaps = true;
// other configurations
});
更新2-Automapper 9及更高版本: 从Automapper 9.0版开始,删除了
CreateMissingTypeMaps
API。Automapper文档现在建议显式配置映射,手动或使用反射
CreateMissingTypeMaps可以在您的配置文件中设置。但是,建议对每个映射显式使用CreateMap,并在每个概要文件的单元测试中调用AssertConfigurationsValid,以防止出现无提示错误
public class MyProfile : Profile {
CreateMissingTypeMaps = true;
// Mappings...
}
将
CreateMissingTypeMaps
选项设置为true。这是ASP.NET Core的packageAutoMapper.Extensions.Microsoft.DependencyInjection
示例:
public class Startup {
//...
public void ConfigureServices(IServiceCollection services) {
//...
services.AddAutoMapper(cfg => { cfg.CreateMissingTypeMaps = true; });
//...
}
//...
}
今天,我在一些通用代码中也需要它。我试过这样的方法:
private static IMapper CreateMapper<T1, T2>()
{
return new MapperConfiguration(cfg => FillMapperConfig(cfg, typeof(T1), typeof(T2)))
.CreateMapper();
}
private static void FillMapperConfig(IMapperConfigurationExpression cfg, Type T1, Type T2)
{
if (T1 == T2)
{
return;
}
cfg.CreateMap(T1, T2);
foreach (PropertyInfo propertyInfo in T1.GetProperties())
{
PropertyInfo correspondingProperty =
T2.GetProperties()
.FirstOrDefault(p =>
p.Name == propertyInfo.Name);
if (correspondingProperty != null)
{
if (propertyInfo.PropertyType.IsGenericType &&
correspondingProperty.PropertyType.IsGenericType)
{
FillMapperConfig(
cfg,
propertyInfo.PropertyType.GetGenericArguments()[0],
correspondingProperty.PropertyType.GetGenericArguments()[0]);
}
else if (propertyInfo.PropertyType.IsClass &&
correspondingProperty.PropertyType.IsClass)
{
FillMapperConfig(
cfg,
propertyInfo.PropertyType,
correspondingProperty.PropertyType);
}
}
}
}
IMapper mapper = CreateMapper<ClassA, ClassB>();
private static IMapper CreateMapper()
{
返回新的MapperConfiguration(cfg=>FillMapperConfig(cfg,typeof(T1),typeof(T2)))
.CreateMapper();
}
私有静态void FillMapperConfig(IMapperConfigurationExpression cfg,类型T1,类型T2)
{
如果(T1==T2)
{
返回;
}
CreateMap(T1,T2);
foreach(T1.GetProperties()中的PropertyInfo PropertyInfo)
{
属性信息对应的属性=
T2.GetProperties()
.FirstOrDefault(p=>
p、 Name==propertyInfo.Name);
if(correspondingProperty!=null)
{
如果(propertyInfo.PropertyType.IsGenericType&&
对应的Property.PropertyType.IsGenericType)
{
FillMapperConfig(
cfg,
propertyInfo.PropertyType.GetGenericArguments()[0],
对应的Property.PropertyType.GetGenericArguments()[0]);
}
else if(propertyInfo.PropertyType.IsClass&&
对应的Property.PropertyType.IsClass)
{
FillMapperConfig(
cfg,
propertyInfo.PropertyType,
对应的属性。属性类型);
}
}
}
}
然后我可以这样做:
private static IMapper CreateMapper<T1, T2>()
{
return new MapperConfiguration(cfg => FillMapperConfig(cfg, typeof(T1), typeof(T2)))
.CreateMapper();
}
private static void FillMapperConfig(IMapperConfigurationExpression cfg, Type T1, Type T2)
{
if (T1 == T2)
{
return;
}
cfg.CreateMap(T1, T2);
foreach (PropertyInfo propertyInfo in T1.GetProperties())
{
PropertyInfo correspondingProperty =
T2.GetProperties()
.FirstOrDefault(p =>
p.Name == propertyInfo.Name);
if (correspondingProperty != null)
{
if (propertyInfo.PropertyType.IsGenericType &&
correspondingProperty.PropertyType.IsGenericType)
{
FillMapperConfig(
cfg,
propertyInfo.PropertyType.GetGenericArguments()[0],
correspondingProperty.PropertyType.GetGenericArguments()[0]);
}
else if (propertyInfo.PropertyType.IsClass &&
correspondingProperty.PropertyType.IsClass)
{
FillMapperConfig(
cfg,
propertyInfo.PropertyType,
correspondingProperty.PropertyType);
}
}
}
}
IMapper mapper = CreateMapper<ClassA, ClassB>();
IMapper mapper=CreateMapper();
这将创建一个从ClassA到ClassB的映射,其中包含ClassA和ClassB的所有子属性(如果它们具有相同的名称),并递归地表示子属性
例如:
public class ClassA {
public int IntProperty { get; set; }
public ClassASubProperty SubProperty { get; set; }
public List<ClassAListItem> ListItems { get; set; }
}
public class ClassB {
public int IntProperty { get; set; }
public ClassBSubProperty SubProperty { get; set; }
public List<ClassBListItem> ListItems { get; set; }
}
公共类ClassA{
公共int属性{get;set;}
公共类AsubProperty子属性{get;set;}
公共列表列表项{get;set;}
}
公共B类{
公共int属性{get;set;}
public ClassBSubProperty子属性{get;set;}
公共列表列表项{get;set;}
}
这将产生与IMapper等效的结果:
new MapperConfiguration(cfg => {
cfg.CreateMap<ClassA, ClassB>();
cfg.CreateMap<ClassASubProperty, ClassBSubProperty>();
cfg.CreateMap<ClassAListItem, ClassBListItem>()
}).CreateMapper();
新的MapperConfiguration(cfg=>{
CreateMap();
CreateMap();
cfg.CreateMap()
}).CreateMapper();
有全局设置吗?@ChadKapatch,我不知道of@ThomasLevesque:不适用于我,给出如下错误,不包含“CreateMissingTypeMaps”的定义,并且找不到接受类型为的第一个参数的扩展方法。有什么想法吗?谢谢,@thomasleveque,但似乎CreateMapper()并没有被用来代替DynamicMap(),我的UserProfileVM model=AutoMapper.Mapper.DynamicMap(objUser);我想从这些中删除上面的错误…CreateMapper()对这些情况有帮助吗?@Bharat,对不起,我不明白你的问题是什么。您可能应该发布一个包含更多详细信息的完整问题。DynamicMap现在已过时,Mapper.Map(foo,opts=>opts.CreateMissingTypeMaps=true)
是推荐的备选方案。只有这对我有效,在映射过程中设置它。初始化不起作用。仅供参考,CreateMissingTypeMaps属性应在Configure方法内设置。CreateMissingTypeMaps已过时:“9.0版中将删除对自动创建的映射的支持。您需要手动或使用反射显式配置映射。还考虑属性映射()。