C# 使用反射创建 AutoMapper 映射

标签 c# reflection automapper

我需要从 n 个类创建一个映射(使用 AutoMapper),这些类都派生自一个抽象类到一个契约类

例如:

public abstract class bar
{
   public string Field1 {get; set;}       
   public someClass Field2 {get; set;}
}

public class foo1bar: bar
{
 // members
}

public class foo2bar: bar
{
 // members
}

public class barContract
{
  public string Field1 {get; set;}

  // this will use existing someClass.Description field
  public string Field2Description {get; set;} 
}

bar 类的实现是多种多样的,而且很可能会发生变化(将添加更多)。由于 Automapper 无法映射到抽象类(因此构造函数 mapperConfiguration.CreateMap<bar, barContract>() 不正确),我想知道是否可以使用反射来查找所有“实现”bar 类的类并“自动”映射它们

 var type = typeof(bar);
            var types = AppDomain.CurrentDomain.GetAssemblies()
                .SelectMany(s => s.GetTypes())
                .Where(p => type.IsAssignableFrom(p));

我有类型,我正在尝试调用 CreateMap。 由于类型现在是一个变量,我再次使用反射创建了一个通用方法:

foreach (Type t in types)
{
mapperConfiguration.GetType().GetMethod("CreateMap")
              .MakeGenericMethod(t, typeof(barContract))
              .Invoke(mapperConfiguration, null);
}

问题是 CreateMap 不是从 mapperConfiguration 实例中提取的类型的成员 - 当我尝试按名称提取方法时,我得到 null。我看到它是在 IProfileExpression 中定义的,所以我试图从接口(interface)中提取方法: typeof(IProfileExpression).GetMethod("CreateMap")我得到 System.Reflection.AmbiguousMatchException - 什么是好的,但是在 GetMethod 中使用 System.Reflection.BindingFlags 更具体我再次得到空值。

我做错了什么,或者如何解决映射问题?

最佳答案

您可以创建从一种类型到另一种类型的映射 CreateMap(SouceType, DestinationType));

public abstract class Bar
{
    public string Field1 { get; set; }
}

public class Foo1bar : Bar
{
    // members
}

public class Foo2bar : Bar
{
    // members
}

public class BarContract
{
    public string Field1 { get; set; }

    // this will use existing someClass.Description field
    public string Field2Description { get; set; }
}

class Program
{
    static void Main(string[] args)
    {
        AutoMapperConfiguration.Init();

        var foo1 = new Foo1bar {Field1 = "One"};
        var barContract1=AutoMapperConfiguration.Mapper.Map<Foo1bar, BarContract>(foo1);
        Console.WriteLine("barContract1.Field1: " + barContract1.Field1);

        var foo2 = new Foo2bar {Field1 = "Two"};
        var barContract2=AutoMapperConfiguration.Mapper.Map<Foo2bar, BarContract>(foo2);
        Console.WriteLine("barContract2.Field1: " + barContract2.Field1);

        Console.ReadLine();
    }

    public static class AutoMapperConfiguration
    {
        public static void Init()
        {
            MapperConfiguration = new MapperConfiguration(cfg =>
            {
                var types = Assembly.GetExecutingAssembly().GetTypes()
                    .Where(type => !string.IsNullOrEmpty(type.Namespace) &&
                                    type.BaseType != null &&
                                    type.BaseType == typeof(Bar));
                foreach (Type type in types)
                {
                    cfg.CreateMap(type, typeof(BarContract));
                }
            });

            Mapper = MapperConfiguration.CreateMapper();
        }

        public static IMapper Mapper { get; private set; }

        public static MapperConfiguration MapperConfiguration { get; private set; }
    }
}

输出

enter image description here

关于C# 使用反射创建 AutoMapper 映射,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40344660/

相关文章:

c# - 通过 Google Apps 和 ASP.net 应用程序使用 Google 联合登录

c# - Automapper:序列不包含任何元素。

automapper - 何时使用值格式化程序以及何时使用值解析器

java - 从 JPA 获取 @Id 的 DataType

java - 如何以编程方式导入 Java 类

Java new泛型类的实例

c# - 通过 NHibernate 和 AutoMapper 将 DTO 的实体 ID 转换为域的实体

c# - C# 样本/用法的 Encog 正则化

c# - 如何将文件复制到团队资源管理器中的文档?

c# - 按钮 anchor 的重新定位不如组中的其他控件快