【问题标题】:Convert 1 class to another class with same fields将 1 个类转换为具有相同字段的另一个类
【发布时间】:2017-09-09 05:04:22
【问题描述】:

假设我有 2 个类(其中一个来自我的实体框架,另一个是全局的,它在整个应用程序中可用,而 EF 一个不可用)它们都具有相同的属性和字段。除了该示例之外,是否有更简单快捷的方法将 Entity 类转换为全局类?

全球一:

 public class CompanyOwner
{
    public Guid OwnerId { get; set; }
    public string CompanyName { get; set; }
    public string Address { get; set; }
    public string Phone { get; set; }
    public string Email { get; set; }
}

实体模型类

 public class dbOwner
{
    public Guid OwnerId { get; set; }
    public string CompanyName { get; set; }
    public string Address { get; set; }
    public string Phone { get; set; }
    public string Email { get; set; }
}

我现在的做法:

        CompanyOwner owner = new CompanyOwner();  
        Owner dbOwner = entities.FirstOrDefault(.....)// some LINQ
        owner.CompanyName = dbOwner.CompanyName;
        owner.Address = dbOwner.Address;
        owner.Email = dbOwner.Email;
        owner.Phone = dbOwner.Phone;

【问题讨论】:

    标签: c# .net mapping


    【解决方案1】:

    AutoMapper 是你的朋友。

    从主页

    AutoMapper 是一个对象-对象映射器。对象-对象映射通过 将一种类型的输入对象转换为一种类型的输出对象 不同的类型。 AutoMapper 的有趣之处在于它提供了 一些有趣的约定可以消除计算中的脏活 找出如何将类型 A 映射到类型 B。只要类型 B 如下 AutoMapper 的既定约定,几乎是零配置 需要映射两种类型。

    【讨论】:

      【解决方案2】:

      这是唯一的强制转换方法,否则您可以创建同一个类的两个不同对象。但我更喜欢创建全局类,它在我们当时从两个不同的表中获取数据时也很有用只需在全局类中添加字段。

      【讨论】:

        【解决方案3】:

        由于在这样的映射中存在许多微小的边缘情况和感兴趣的特殊功能,因此建议您使用 gsharp推荐的 AutoMapper 等库>。

        但是,为了让您了解如何构建这样的映射器,这里有一个非常简单的。这将查找目标类型的所有属性,其名称与源类型上的属性匹配(大小写不变),然后生成一个编译的委托,该委托实例化目标类型的新实例(在这种情况下使用默认构造函数)和然后使用源实例中的值初始化属性。

        这绝对是最基本的形式,但应该让您了解映射器的工作原理。然后通过分析所有构造函数并找到合适的构造函数来扩展它(以支持不可变类型);当属性类型不匹配时执行类型转换操作;您添加了识别名称匹配的功能,即使命名约定不同(my_property ~ MyProperty ~ myProperty);名单还在继续。

        实施:

        Func<TSource, TTarget> CreateMapper<TSource, TTarget>()
            where TTarget : new()
        {
            var sourceProperties = typeof(TSource)
                .GetProperties()
                .Where(x => x.CanRead);
            var targetProperties = typeof(TTarget)
                .GetProperties()
                .Where(x => x.CanWrite)
                .ToDictionary(x => x.Name, x => x, StringComparer.OrdinalIgnoreCase);
        
            var source = Expression.Parameter(typeof(TSource), "source");
            var target = Expression.Variable(typeof(TTarget));
            var allocate = Expression.New(typeof(TTarget));
            var assignTarget = Expression.Assign(target, allocate);
        
            var statements = new List<Expression>();
            statements.Add(assignTarget);
        
            foreach (var sourceProperty in sourceProperties)
            {
                PropertyInfo targetProperty;
                if (targetProperties.TryGetValue(sourceProperty.Name, out targetProperty))
                {
                    var assignProperty = Expression.Assign(
                        Expression.Property(target, targetProperty),
                        Expression.Property(source, sourceProperty));
                    statements.Add(assignProperty);
                }
            }
        
            statements.Add(target);
        
            var body = Expression.Block(new[] { target }, statements);
        
            return Expression.Lambda<Func<TSource, TTarget>>(body, source).Compile();
        }
        

        用法:

        var mapper = CreateMapper<dbOwner, CompanyOwner>();
        
        var source = new dbOwner
        {
            OwnerId = Guid.NewGuid(),
            CompanyName = "My Name",
            Address = "My Address",
            Phone = "My Phone",
            Email = "My Email"
        };
        
        var mapped = mapper(source);
        

        【讨论】:

        • 没有像我这样懒惰的加分项 ;-)
        • 这实际上很有用.. tnx
        猜你喜欢
        • 2011-04-10
        • 1970-01-01
        • 1970-01-01
        • 2018-02-21
        • 2021-08-14
        • 2021-04-16
        • 1970-01-01
        • 2019-09-05
        • 1970-01-01
        相关资源
        最近更新 更多