Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/opencv/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# Automapper |仅当不是默认值/初始值时才映射_C#_Automapper - Fatal编程技术网

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));
        }
    }
}