C# Automapper |仅当不是默认值/初始值时才映射
我想有一个通用的方法来映射属性,只有当它们被更改,而不是默认值。 假设你有这两门课C# Automapper |仅当不是默认值/初始值时才映射,c#,automapper,C#,Automapper,我想有一个通用的方法来映射属性,只有当它们被更改,而不是默认值。 假设你有这两门课 public class Source { public string Foo { get; set; } = "Foo"; public string Bar { get; set; } = "Bar"; } public class Destination { public string Foo { get; set; } = "Foo
public class Source
{
public string Foo { get; set; } = "Foo";
public string Bar { get; set; } = "Bar";
}
public class Destination
{
public string Foo { get; set; } = "Foo of Destination";
public string Bar { get; set; } = "Bar of Destination";
}
现在我想将Source映射到Destination,如果Source.Foo的属性仍然是“Foo”,它应该更改为“Foo of Destination”,但是当Source.Foo的值不同于“Foo”(默认值)时,它应该真正映射属性。
我找不到用automapper做这件事的方法
[TestMethod]
public void ChangeAllProperties()
{
var source = new Source();
var destination = _mapper.Map<Destination>(source);
var defaultDestination = new Destination();
Assert.AreEqual(destination.Bar, defaultDestination.Bar); // Should be the Default Value of "Destination"
Assert.AreEqual(destination.Foo, defaultDestination.Foo); // Should be the Default Value of "Destination"
}
[TestMethod]
public void ChangeDefaultProperty()
{
var source = new Source();
source.Bar = "Custom Bar!";
var destination = _mapper.Map<Destination>(source);
var defaultDestination = new Destination();
Assert.AreEqual(destination.Bar, source.Bar); // Should be Value of Source
Assert.AreEqual(destination.Foo, defaultDestination.Foo); // Should be the Default Value of "Destination"
}
[TestMethod]
public void AlLChanged()
{
var source = new Source();
source.Foo = "Custom Foo!";
source.Bar = "Custom Bar!";
var destination = _mapper.Map<Destination>(source);
Assert.AreEqual(destination.Bar, source.Bar); // Should be Value of Source
Assert.AreEqual(destination.Foo, source.Foo); // Should be Value of Source
}
[TestMethod]
public void ChangeAllProperties()
{
var source=新源();
var destination=\u mapper.Map(源);
var defaultDestination=新目的地();
Assert.AreEqual(destination.Bar,defaultDestination.Bar);//应该是“destination”的默认值
Assert.AreEqual(destination.Foo,defaultDestination.Foo);//应该是“destination”的默认值
}
[测试方法]
public void ChangeDefaultProperty()
{
var source=新源();
source.Bar=“自定义栏!”;
var destination=\u mapper.Map(源);
var defaultDestination=新目的地();
Assert.AreEqual(destination.Bar,source.Bar);//应该是source的值
Assert.AreEqual(destination.Foo,defaultDestination.Foo);//应该是“destination”的默认值
}
[测试方法]
public void AlLChanged()
{
var source=新源();
source.Foo=“自定义Foo!”;
source.Bar=“自定义栏!”;
var destination=\u mapper.Map(源);
Assert.AreEqual(destination.Bar,source.Bar);//应该是source的值
Assert.AreEqual(destination.Foo,source.Foo);//应该是source的值
}
检查自动映射条件映射-
基本上,您可以这样做(从示例中):
var配置=新的MapperConfiguration(cfg=>{
cfg.CreateMap()
.ForMember(dest=>dest.baz,opt=>opt.Condition(src=>(src.baz>=0));
});
opt.Condition()。我能够创建更通用的东西,所以我不需要为每个成员定义它,并检查属性的默认值。
这就是我想出的解决办法。仅当源中也存在具有相同名称和类型的目标成员时,才会检查默认值
public class FooBarProfile: Profile
{
public FooBarProfile()
{
CreateMap<Source, Destination>()
.ForAllMembers(opt => opt.Condition(src => OnlyIfChanged(src, opt.DestinationMember)));
// And if you need reversed...
CreateMap<Destination, Source>()
.ForAllMembers(opt => opt.Condition(src => OnlyIfChanged(src, opt.DestinationMember)));
}
private static bool OnlyIfChanged<TSource>(TSource src, MemberInfo destinationMember) where TSource : new()
{
// Check if DestinationMember exists in TSource (same Name & Type)
var sourceMember = typeof(TSource).GetMembers().FirstOrDefault(e => e.Name == destinationMember.Name && e.MemberType == destinationMember.MemberType);
if (sourceMember != null)
{
var defaultOfSource = new TSource();
// Map only if Value of Source is differnent than the default soruce value
return (GetValue(sourceMember,src)?.Equals(GetValue(sourceMember,defaultOfSource)) == false);
}
return true;
}
// Helper-Method to get Value from a MemberInfo
private static object GetValue(MemberInfo memberInfo, object forObject)
{
switch (memberInfo.MemberType)
{
case MemberTypes.Field:
return ((FieldInfo)memberInfo).GetValue(forObject);
case MemberTypes.Property:
return ((PropertyInfo)memberInfo).GetValue(forObject);
default:
throw new ArgumentException("Member is not Field or Property.", nameof(memberInfo));
}
}
}
公共类FooBarProfile:Profile
{
公共FooBarProfile()
{
CreateMap()
.ForAllMembers(opt=>opt.Condition(src=>OnlyIfChanged(src,opt.DestinationMember));
//如果你需要反转。。。
CreateMap()
.ForAllMembers(opt=>opt.Condition(src=>OnlyIfChanged(src,opt.DestinationMember));
}
私有静态bool OnlyIfChanged(TSource src,MemberInfo destinationMember),其中TSource:new()
{
//检查TSource中是否存在DestinationMember(名称和类型相同)
var sourceMember=typeof(TSource).GetMembers().FirstOrDefault(e=>e.Name==destinationMember.Name&&e.MemberType==destinationMember.MemberType);
if(sourceMember!=null)
{
var defaultOfSource=new TSource();
//仅当源的值与默认soruce值不同时才映射
返回(GetValue(sourceMember,src)?.Equals(GetValue(sourceMember,defaultOfSource))==false);
}
返回true;
}
//用于从MemberInfo获取值的Helper方法
私有静态对象GetValue(MemberInfo MemberInfo、object forObject)
{
开关(memberInfo.MemberType)
{
案例成员类型。字段:
return((FieldInfo)memberInfo).GetValue(forObject);
案例成员类型。属性:
返回((PropertyInfo)memberInfo).GetValue(forObject);
违约:
抛出新ArgumentException(“成员不是字段或属性。”,nameof(memberInfo));
}
}
}
public class FooBarProfile: Profile
{
public FooBarProfile()
{
CreateMap<Source, Destination>()
.ForAllMembers(opt => opt.Condition(src => OnlyIfChanged(src, opt.DestinationMember)));
// And if you need reversed...
CreateMap<Destination, Source>()
.ForAllMembers(opt => opt.Condition(src => OnlyIfChanged(src, opt.DestinationMember)));
}
private static bool OnlyIfChanged<TSource>(TSource src, MemberInfo destinationMember) where TSource : new()
{
// Check if DestinationMember exists in TSource (same Name & Type)
var sourceMember = typeof(TSource).GetMembers().FirstOrDefault(e => e.Name == destinationMember.Name && e.MemberType == destinationMember.MemberType);
if (sourceMember != null)
{
var defaultOfSource = new TSource();
// Map only if Value of Source is differnent than the default soruce value
return (GetValue(sourceMember,src)?.Equals(GetValue(sourceMember,defaultOfSource)) == false);
}
return true;
}
// Helper-Method to get Value from a MemberInfo
private static object GetValue(MemberInfo memberInfo, object forObject)
{
switch (memberInfo.MemberType)
{
case MemberTypes.Field:
return ((FieldInfo)memberInfo).GetValue(forObject);
case MemberTypes.Property:
return ((PropertyInfo)memberInfo).GetValue(forObject);
default:
throw new ArgumentException("Member is not Field or Property.", nameof(memberInfo));
}
}
}