代码之家  ›  专栏  ›  技术社区  ›  keithwarren7

如何通过匹配字段或属性名从不同的类复制数据

  •  3
  • keithwarren7  · 技术社区  · 15 年前

    public class A : B
    {
        public string prop1;
        public int prop2;
    }
    
    public class B
    {
        public byte propX;
        public float propY;
    }
    
    public class C
    {
        public byte propX;
        public float propY;
        public string prop1;
        public int prop2;
    }
    
    public class Merger
    {
        public static object Merge(object copyFrom, object copyTo)
        { 
            //do some work
            //maybe <T> generically refactor?
        }
    }
    

    合并类只是一个psuedo示例,通过泛型实现这一点是最佳的,但我首先要问的是,这样的功能是否已经存在。我可以想象自己用反射来做这件事,但我只是想先把它扔掉,得到更好的想法。

    4 回复  |  直到 15 年前
        1
  •  8
  •   marc_s MisterSmith    15 年前

    查看工具和库,如 AutoMapper -这样的案子处理起来就容易多了!不需要重新发明轮子-只要使用工具!:-)

    Mapper.CreateMap<A, C>();
    

    之后,你可以让AutoMapper根据这个映射,从A的一个实例映射到C的一个实例,如下所示:

    C yourC = Mapper.Map<A, C>(instanceOfA);
    

    AutoMapper基于属性名(和类型)进行默认映射,但您可以通过多种方式对其进行扩展和影响,以包括从一个属性到另一个属性的映射,即使名称(或类型)与100%不匹配。这是相当灵活和成熟的-绝对值得一看认真!

        2
  •  1
  •   Timwi    15 年前
    using System;
    using System.Linq;
    using System.Reflection;
    
    public class Merger
    {
        public static TTarget Merge<TTarget>(object copyFrom) where TTarget : new()
        {
            var flags = BindingFlags.Instance | BindingFlags.Public |
                        BindingFlags.NonPublic;
            var targetDic = typeof(TTarget).GetFields(flags)
                                           .ToDictionary(f => f.Name);
            var ret = new TTarget();
            foreach (var f in copyFrom.GetType().GetFields(flags))
            {
                if (targetDic.ContainsKey(f.Name))
                    targetDic[f.Name].SetValue(ret, f.GetValue(copyFrom));
                else
                    throw new InvalidOperationException(string.Format(
                        "The field “{0}” has no corresponding field in the type “{1}”.",
                        f.Name, typeof(TTarget).FullName));
            }
            return ret;
        }
    }
    
    class Program
    {
        static void Main(string[] args)
        {
            var a = new A { prop1 = "one", prop2 = 2, propX = 127, propY = 0.47f };
            var c = Merger.Merge<C>(a);
            Console.WriteLine(c.prop1);  // prints one
            Console.WriteLine(c.prop2);  // prints 2
            Console.WriteLine(c.propX);  // prints 127
            Console.WriteLine(c.propY);  // prints 0.47
        }
    }
    
        3
  •  0
  •   code4life    15 年前

    你的提议 Merger

    public class Merger
    {
        public static object Merge(object copyFrom, object copyTo)
        { 
            var xmlContent = MyXMLSerializationMethod(copyFrom);
            MyXMLDeserializationMethod(xmlContent, typeof(copyTo), out copyTo);
            return copyTo;
        }
    }
    
        4
  •  0
  •   keithwarren7    15 年前

    关于在MVVM和MVC环境下使用AutoMapper解决这个问题的好文章

    http://www.bengtbe.com/blog/post/2009/04/14/Using-AutoMapper-to-map-view-models-in-ASPNET-MVC.aspx