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

时间:2016-06-01 00:45:46

标签: 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 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);
}   

Property1Property3目前由AutoMapper设置。然后,我必须使用函数,一些其他标记循环遍历DestinationObjects列表以设置Property4Property6。我知道这可能不是AutoMapper的用途,但我真的想避免两次循环对象(一次是AutoMapper,一次是我自己)。静态SetupProperties函数在其他地方使用,所以我希望保持这样。 AutoMapper可以设置吗?感谢您提前提供任何帮助。

2 个答案:

答案 0 :(得分:0)

这实际上取决于Utility.SetupProperties中发生的事情,但是通过在Automapper中使用之前和之后的映射操作,可以通过一些逻辑来获得更复杂的映射情况:https://github.com/AutoMapper/AutoMapper/wiki/Before-and-after-map-actions

Mapper.Initialize(cfg => {
  cfg.CreateMap<SourceObject, DestinationObject>()
    .BeforeMap((src, dest) => 
    {
      //Do some work here and set properties. 
    })
});

答案 1 :(得分:0)

通常,您可以使用AfterMap并通过闭包捕获您想要传入的任何其他参数(如第二个wiki示例中所示)。但是,由于您在集合之间进行转换,因此在这种情况下,我不认为每个项目都有一种干净的方法。

我已经做了一些挖掘,我认为你可以使用ITypeConverter<TSource, TDestination>来完成你正在尝试的转换。

我不得不对Utility.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; }
    }
}