C# 使用AutoMapper运行函数,根据其他参数设置多个属性

C# 使用AutoMapper运行函数,根据其他参数设置多个属性,c#,automapper,C#,Automapper,我需要帮助看看AutoMapper是否能做到这一点。我的代码已经被简化了,但它让人明白了这一点 public class SourceObject { public string Property1 { get; set; } public string Property2 { get; set; } public string Property3 { get; set; } } public class DestinationObject { public

我需要帮助看看AutoMapper是否能做到这一点。我的代码已经被简化了,但它让人明白了这一点

public class SourceObject
{
    public string Property1 { get; set; }
    public string Property2 { get; set; }
    public string Property3 { get; set; }

}

public class DestinationObject
{
    public string Property1 { get; set; }
    public string Property2 { get; set; }
    public string Property3 { get; set; }
    public string Property4 { get; set; }
    public string Property5 { get; set; }
    public string Property6 { get; set; }
}

var vm = new ViewModel
{
    Objects = Mapper.Map<IList<SourceObject>, IEnumerable<DestinationObject>>(dests)
};

foreach (var destObj in vm.Objects)
{
    Utility.SetupProperties(destObj, new AnotherDependency(), destObj.Property3,
        someFlag, anotherFlag);
}   
公共类源对象
{
公共字符串属性1{get;set;}
公共字符串属性2{get;set;}
公共字符串属性3{get;set;}
}
公共类目标对象
{
公共字符串属性1{get;set;}
公共字符串属性2{get;set;}
公共字符串属性3{get;set;}
公共字符串属性4{get;set;}
公共字符串属性5{get;set;}
公共字符串属性6{get;set;}
}
var vm=新的视图模型
{
Objects=Mapper.Map(dests)
};
foreach(vm.Objects中的var destObj)
{
Utility.SetupProperties(destObj,新的另一个依赖项(),destObj.Property3,
一些旗帜,另一个旗帜);
}   

Property1
Property3
目前由AutoMapper设置。然后,我必须循环查看
DestinationObjects
列表,以设置
Property4
Property6
,并使用函数和一些附加标志。我知道这可能不是AutoMapper的用途,但我确实希望避免在对象中循环两次(一次由AutoMapper循环,一次由我自己循环)。静态
SetupProperties
函数在其他地方使用,因此我想保留它。AutoMapper可以设置这个吗?感谢您提前提供的帮助。

这确实取决于Utility.SetupProperties内部发生的情况,但通过使用Automapper中的“前后映射”操作,可能会有更复杂的映射情况,并带有一些逻辑:

Mapper.Initialize(cfg=>{
cfg.CreateMap()
.BeforeMap((src,dest)=>
{
//在这里做一些工作并设置属性。
})
});

这实际上取决于Utility.SetupProperties内部发生的情况,但通过使用Automapper中的前后映射操作,可以使用一些逻辑来实现更复杂的映射情况:

Mapper.Initialize(cfg=>{
cfg.CreateMap()
.BeforeMap((src,dest)=>
{
//在这里做一些工作并设置属性。
})
});
通常,您可以使用并捕获希望通过闭包传递的任何附加参数(如第二个wiki示例)。然而,由于您要在集合之间进行转换,我认为在这种情况下,没有一种干净的方法可以对每个项目进行转换

我已经做了一些挖掘,我想你可以用它来完成你正在尝试的转换

我不得不对
实用程序.SetupProperties
等的实现和用例进行一些猜测。但我认为下面的概念验证控制台应用程序应该演示如何完成自定义转换:

using System;
using System.Collections.Generic;
using AutoMapper;

namespace ConsoleApplication
{
    public class Program
    {
        public static void Main(string[] args)
        {
            var sourceObjects = new SourceObject[] {
                new SourceObject{Property1 = "prop 1A"},
                new SourceObject{Property2 = "Prop 2B"},
                new SourceObject{Property3 = "Prop 3C"}};

            var someFlag = true;
            var anotherFlag = false;

            Mapper.Initialize(cfg =>
            {
                cfg.CreateMap<SourceObject, DestinationObject>().ConvertUsing<CustomConverter>();
            });

            var vm = new ViewModel
            {
                Objects = Mapper.Map<IList<SourceObject>, IEnumerable<DestinationObject>>(sourceObjects, opts =>
                {
                    opts.Items.Add("AnotherDependency", new AnotherDependency { Foo = "bar" });
                    opts.Items.Add("flag1", someFlag);
                    opts.Items.Add("flag2", anotherFlag);
                })
            };

            foreach (var obj in vm.Objects)
            {
                Console.WriteLine($"[{obj.Property1}, {obj.Property2}, {obj.Property3}, {obj.Property4}, {obj.Property5}, {obj.Property6}]");
            }
        }
    }

    public class CustomConverter : ITypeConverter<SourceObject, DestinationObject>
    {
        public DestinationObject Convert(ResolutionContext context)
        {
            return Convert(context.SourceValue as SourceObject, context);
        }

        public DestinationObject Convert(SourceObject source, ResolutionContext context)
        {
            var dest = new DestinationObject
            {
                Property1 = source?.Property1,
                Property2 = source?.Property2,
                Property3 = source?.Property3
            };

            var items = context.Options.Items;

            Utility.SetupProperties(dest,
                items["AnotherDependency"] as AnotherDependency,
                dest.Property3,
                items["flag1"] as bool? ?? false,
                items["flag2"] as bool? ?? false);

            return dest;
        }
    }

    public static class Utility
    {
        public static void SetupProperties(DestinationObject x, AnotherDependency ad, string a, bool b, bool c)
        {
            x.Property4 = ad.Foo;
            if (b || c)
            {
                x.Property5 = ad?.ToString() ?? a;
            }
            if (b && c)
            {
                x.Property6 = ad?.ToString() ?? a;
            }
            return;
        }
    }
    public class ViewModel
    {
        public IEnumerable<DestinationObject> Objects { get; set; }
    }
    public class AnotherDependency { public string Foo { get; set; } }
    public class SourceObject
    {
        public string Property1 { get; set; }
        public string Property2 { get; set; }
        public string Property3 { get; set; }
    }
    public class DestinationObject
    {
        public string Property1 { get; set; }
        public string Property2 { get; set; }
        public string Property3 { get; set; }
        public string Property4 { get; set; }
        public string Property5 { get; set; }
        public string Property6 { get; set; }
    }
}
使用系统;
使用System.Collections.Generic;
使用自动制版机;
命名空间控制台应用程序
{
公共课程
{
公共静态void Main(字符串[]args)
{
var sourceObjects=新的SourceObject[]{
新的SourceObject{Property1=“prop 1A”},
新的SourceObject{Property2=“Prop 2B”},
新的SourceObject{Property3=“Prop 3C”};
var someFlag=true;
var anotherFlag=false;
Mapper.Initialize(cfg=>
{
CreateMap().ConvertUsing();
});
var vm=新的视图模型
{
Objects=Mapper.Map(sourceObjects,opts=>
{
添加(“AnotherDependency”,新的AnotherDependency{Foo=“bar”});
选择项。添加(“flag1”,someFlag);
选择项。添加(“标志2”,另一个标志);
})
};
foreach(vm.Objects中的var obj)
{
WriteLine($“[{obj.Property1},{obj.Property2},{obj.Property3},{obj.Property4},{obj.Property5},{obj.Property6}]”);
}
}
}
公共类CustomConverter:ITypeConverter
{
公共目标对象转换(ResolutionContext上下文)
{
返回Convert(context.SourceValue作为SourceObject,context);
}
公共DestinationObject转换(SourceObject源、ResolutionContext上下文)
{
var dest=新的目标对象
{
Property1=源?Property1,
Property2=源?。Property2,
Property3=源?.Property3
};
var items=context.Options.items;
实用程序设置属性(dest,
项[“另一个依赖项”]作为另一个依赖项,
目的地财产3,
项目[“flag1”]为布尔???假,
项目[“flag2”]为布尔???假);
返回目的地;
}
}
公共静态类实用程序
{
公共静态void设置属性(DestinationObject x、另一个依赖项ad、字符串a、布尔b、布尔c)
{
x、 不动产4=不动产;
if(b | | c)
{
x、 Property5=ad?.ToString()?a;
}
如果(b&c)
{
x、 Property6=ad?.ToString()?a;
}
返回;
}
}
公共类视图模型
{
公共IEnumerable对象{get;set;}
}
公共类另一个依赖项{public string Foo{get;set;}}
公共类源对象
{
公共字符串属性1{get;set;}
公共字符串属性2{get;set;}
公共字符串属性3{get;set;}
}
公共类目标对象
{
公共字符串属性1{get;set;}
公共字符串属性2{get;set;}
公共字符串属性3{get;set;}
公共字符串属性4{get;set;}
公共字符串属性5{get;set;}
公共字符串属性6{get;set;}
}
}
通常,您可以
using System;
using System.Collections.Generic;
using AutoMapper;

namespace ConsoleApplication
{
    public class Program
    {
        public static void Main(string[] args)
        {
            var sourceObjects = new SourceObject[] {
                new SourceObject{Property1 = "prop 1A"},
                new SourceObject{Property2 = "Prop 2B"},
                new SourceObject{Property3 = "Prop 3C"}};

            var someFlag = true;
            var anotherFlag = false;

            Mapper.Initialize(cfg =>
            {
                cfg.CreateMap<SourceObject, DestinationObject>().ConvertUsing<CustomConverter>();
            });

            var vm = new ViewModel
            {
                Objects = Mapper.Map<IList<SourceObject>, IEnumerable<DestinationObject>>(sourceObjects, opts =>
                {
                    opts.Items.Add("AnotherDependency", new AnotherDependency { Foo = "bar" });
                    opts.Items.Add("flag1", someFlag);
                    opts.Items.Add("flag2", anotherFlag);
                })
            };

            foreach (var obj in vm.Objects)
            {
                Console.WriteLine($"[{obj.Property1}, {obj.Property2}, {obj.Property3}, {obj.Property4}, {obj.Property5}, {obj.Property6}]");
            }
        }
    }

    public class CustomConverter : ITypeConverter<SourceObject, DestinationObject>
    {
        public DestinationObject Convert(ResolutionContext context)
        {
            return Convert(context.SourceValue as SourceObject, context);
        }

        public DestinationObject Convert(SourceObject source, ResolutionContext context)
        {
            var dest = new DestinationObject
            {
                Property1 = source?.Property1,
                Property2 = source?.Property2,
                Property3 = source?.Property3
            };

            var items = context.Options.Items;

            Utility.SetupProperties(dest,
                items["AnotherDependency"] as AnotherDependency,
                dest.Property3,
                items["flag1"] as bool? ?? false,
                items["flag2"] as bool? ?? false);

            return dest;
        }
    }

    public static class Utility
    {
        public static void SetupProperties(DestinationObject x, AnotherDependency ad, string a, bool b, bool c)
        {
            x.Property4 = ad.Foo;
            if (b || c)
            {
                x.Property5 = ad?.ToString() ?? a;
            }
            if (b && c)
            {
                x.Property6 = ad?.ToString() ?? a;
            }
            return;
        }
    }
    public class ViewModel
    {
        public IEnumerable<DestinationObject> Objects { get; set; }
    }
    public class AnotherDependency { public string Foo { get; set; } }
    public class SourceObject
    {
        public string Property1 { get; set; }
        public string Property2 { get; set; }
        public string Property3 { get; set; }
    }
    public class DestinationObject
    {
        public string Property1 { get; set; }
        public string Property2 { get; set; }
        public string Property3 { get; set; }
        public string Property4 { get; set; }
        public string Property5 { get; set; }
        public string Property6 { get; set; }
    }
}