2013-04-20 76 views
22

我的问题是,我可以以最易维护的方式将一个对象映射到另一个对象的最佳方式是什么。我无法改变我们得到的Dto对象被设置为更规范化的方式,所以我需要创建一种方法将其映射到我们的对象实现。将一个对象映射到另一个对象的最佳实践

下面是示例代码来说明我需要发生:

class Program 
{ 
    static void Main(string[] args) 
    { 
     var dto = new Dto(); 

     dto.Items = new object[] { 1.00m, true, "Three" }; 
     dto.ItemsNames = new[] { "One", "Two", "Three" };    

     var model = GetModel(dto); 

     Console.WriteLine("One: {0}", model.One); 
     Console.WriteLine("Two: {0}", model.Two); 
     Console.WriteLine("Three: {0}", model.Three); 
     Console.ReadLine(); 
    } 

    private static Model GetModel(Dto dto) 
    { 
     var result = new Model(); 

     result.One = Convert.ToDecimal(dto.Items[Array.IndexOf(dto.ItemsNames, "One")]); 
     result.Two = Convert.ToBoolean(dto.Items[Array.IndexOf(dto.ItemsNames, "Two")]); 
     result.Three = dto.Items[Array.IndexOf(dto.ItemsNames, "Three")].ToString(); 

     return result; 
    } 
} 

class Dto 
{ 
    public object[] Items { get; set; } 
    public string[] ItemsNames { get; set; } 
} 

class Model 
{ 
    public decimal One { get; set; } 
    public bool Two { get; set; } 
    public string Three { get; set; } 
} 

,我认为这将是巨大的,如果我有某种映射类的,将采取在模型对象的PropertyInfo,I型想要转换为,以及我想要提取的“itemname”。有没有人有任何建议,使这个更清洁?

谢谢!

+0

不能确定的映射,但你绝对应该看看泛型和使用泛型集合:http://csharp-station.com/Tutorial/CSharp/Lesson20 – christiandev 2013-04-20 08:17:58

+0

我建议型号的costructor,这需要Dto和映射/转换/检查相应的硬编码,因为当dto中的某些内容发生更改时,您会收到编译错误。反思并因此处理字符串不会帮助您提高可维护性。 – wonko79 2013-04-20 08:24:36

回答

4

这是使用有点反射的可能通用的实现(伪代码,不具有VS现在):

public class DtoMapper<DtoType> 
{ 
    Dictionary<string,PropertyInfo> properties; 

    public DtoMapper() 
    { 
     // Cache property infos 
     var t = typeof(DtoType); 
     properties = t.GetProperties().ToDictionary(p => p.Name, p => p); 
    } 

    public DtoType Map(Dto dto) 
    { 
     var instance = Activator.CreateInstance(typeOf(DtoType)); 

     foreach(var p in properties) 
     { 
      p.SetProperty(
       instance, 
       Convert.Type(
        p.PropertyType, 
        dto.Items[Array.IndexOf(dto.ItemsNames, p.Name)]); 

      return instance; 
     } 
    } 

用法:

var mapper = new DtoMapper<Model>(); 
var modelInstance = mapper.Map(dto); 

这将是缓慢的,当你创建映射器实例,但稍后更快。

+0

不幸的是,这里的需求并不像我希望的那样简单,项目名称也不必与模型中属性的名称相关联,所以我认为这不会起作用。 – Alex 2013-04-22 15:01:16

15

我会选择AutoMapper,这是一个开放源代码和免费的映射库,允许根据约定将一种类型映射到另一种类型(即具有相同名称和相同/衍生/可转换类型的映射公共属性,以及其他许多其他类型smart ones)。使用非常简单,将让你实现这样的事情:

Model model = Mapper.Map<Model>(dto); 

不知道您的具体要求,但AutoMapper还支持custom value resolvers,这将有助于你写一个单一,通用实现您的特定映射的。

+5

我们之前使用过automapper,但由于性能低下,我们有理由放弃它。 – Alex 2013-04-22 15:02:33

+2

同意。完成同样的事情后,最终放弃了更多的工作,首先放下automapper然后编写一个自定义的。 Automapper的性能非常非常慢 – ZolaKt 2015-06-10 12:27:32

+1

我们几乎有与性能相同的问题,不会再使用它。 – 2018-02-12 04:49:19

1
/// <summary> 
/// map properties 
/// </summary> 
/// <param name="sourceObj"></param> 
/// <param name="targetObj"></param> 
private void MapProp(object sourceObj, object targetObj) 
{ 
    Type T1 = sourceObj.GetType(); 
    Type T2 = targetObj.GetType(); 

    PropertyInfo[] sourceProprties = T1.GetProperties(BindingFlags.Instance | BindingFlags.Public); 
    PropertyInfo[] targetProprties = T2.GetProperties(BindingFlags.Instance | BindingFlags.Public); 

    foreach (var sourceProp in sourceProprties) 
    { 
     object osourceVal = sourceProp.GetValue(sourceObj, null); 
     int entIndex = Array.IndexOf(targetProprties, sourceProp); 
     if (entIndex >= 0) 
     { 
      var targetProp = targetProprties[entIndex]; 
      targetProp.SetValue(targetObj, osourceVal); 
     } 
    } 
} 
+0

一个快速和肮脏的方式! – DKM 2017-06-22 19:37:53

相关问题