C# 对象转换器/适配器

C# 对象转换器/适配器,c#,design-patterns,C#,Design Patterns,在C#/.NET中,映射数据字段(某些任意对象)的最佳方法是什么?您从一个RESTful端点/系统“获取”数据,然后将其“发布”到另一个RESTful端点/系统(已知)。下面是一些示例代码。。。 在这段代码中,我正在模拟一个源对象。但在现实中,我正试图以一种动态的方式来写这篇文章。我能得出的唯一结论是,用户有责任提供一个字段映射文件(json或xml),将源对象的数据字段(因为他们可能最了解自己的系统)映射到众所周知的目标系统。 字段映射本质上是一个键值对,目标字段作为“键”,源字段作为“值”。

在C#/.NET中,映射数据字段(某些任意对象)的最佳方法是什么?您从一个RESTful端点/系统“获取”数据,然后将其“发布”到另一个RESTful端点/系统(已知)。下面是一些示例代码。。。 在这段代码中,我正在模拟一个源对象。但在现实中,我正试图以一种动态的方式来写这篇文章。我能得出的唯一结论是,用户有责任提供一个字段映射文件(json或xml),将源对象的数据字段(因为他们可能最了解自己的系统)映射到众所周知的目标系统。 字段映射本质上是一个键值对,目标字段作为“键”,源字段作为“值”。编辑-我在标题中添加了“适配器”

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using System.Reflection;
using NSubstitute;
using Microsoft.Practices.EnterpriseLibrary.Logging;
using Microsoft.Practices.EnterpriseLibrary.Logging.Formatters;
using Microsoft.Practices.EnterpriseLibrary.Logging.TraceListeners;
using System.Diagnostics;

namespace ConsAppJsonNet
{
    class Program
    {
        static void Main(string[] args)
       {
        //GET SOURCE OBJECT
        dynamic sourceObjdyn = GetSourceObj();

        //GET FIELD MAPPINGS
        Dictionary<string, string> fieldMappings = GetFieldMappings();

        //NEW UP DESTINATION OBJECT
        DestinationObject destinationObject = new DestinationObject();

        foreach (var fieldMapping in fieldMappings)
        {
            foreach (var prop in destinationObject.GetType().GetProperties())
            {
                if (prop.Name == fieldMapping.Key)
                {
                    prop.SetValue(destinationObject,    sourceObjdyn.GetType().GetProperty(fieldMapping.Value).GetValue(sourceObjdyn));                        
                    break;
                }
            }
        }

        Console.WriteLine(destinationObject);
        //Console.ReadKey();
    }

    static Dictionary<string,string> GetFieldMappings()
    {
        string jsonFieldMappings = @"       
            {
                ""SSN"":""ssn"",      
                ""GEN_ID"":""sysid"",      
                ""BIRTH_DATE"":""dob""      
            }";

        //DESERALIZE FIELD-MAPPINGS
        Dictionary<string, string> fieldMappings =    JsonConvert.DeserializeObject<Dictionary<string, string>>(jsonFieldMappings);

        return fieldMappings;
    }

    private static dynamic GetSourceObj()
    {
        //MOCK A SOURCE OBJECT
        var sourceObj = Substitute.For<ISourceObject>();
        sourceObj.dob.Returns("10/10/20112");
        sourceObj.ssn.Returns("555-66-5555");
        sourceObj.sysid.Returns("9876");

        return sourceObj;
    }

}//end program

public class DestinationObject
{
    //ctor
    public DestinationObject()
    { }

    public string SSN { get; set; }
    public string GEN_ID { get; set; }
    public string BIRTH_DATE { get; set; }

    public override string ToString()
    {
        return string.Format("BIRTH_DATE = {0},\nSSN = {1},\nGEN_ID = {2}",  this.BIRTH_DATE, this.SSN, this.GEN_ID);
    }

}//end class

public interface ISourceObject
{
     string ssn { get; set; }
     string sysid { get; set; }
     string dob { get; set; }
}

}//end namespace
使用系统;
使用System.Collections.Generic;
使用System.Linq;
使用系统文本;
使用System.Threading.Tasks;
使用Newtonsoft.Json;
使用Newtonsoft.Json.Linq;
运用系统反思;
使用替代品;
使用Microsoft.Practices.EnterpriseLibrary.Logging;
使用Microsoft.Practices.EnterpriseLibrary.Logging.Formatters;
使用Microsoft.Practices.EnterpriseLibrary.Logging.TraceListeners;
使用系统诊断;
名称空间ConsAppJsonNet
{
班级计划
{
静态void Main(字符串[]参数)
{
//获取源对象
动态sourceObjdyn=GetSourceObj();
//获取字段映射
Dictionary fieldMappings=GetFieldMappings();
//新的上行目标对象
DestinationObject DestinationObject=新建DestinationObject();
foreach(fieldMappings中的变量fieldMapping)
{
foreach(destinationObject.GetType().GetProperties()中的var prop)
{
if(prop.Name==fieldMapping.Key)
{
SetValue(destinationObject,sourceObjdyn.GetType().GetProperty(fieldMapping.Value).GetValue(sourceObjdyn));
打破
}
}
}
控制台写入线(destinationObject);
//Console.ReadKey();
}
静态字典GetFieldMappings()
{
字符串jsonFieldMappings=@”
{
“SSN”:“SSN”,
“GEN_ID”:“sysid”,
“出生日期”:“出生日期”
}";
//反序列化字段映射
Dictionary fieldMappings=JsonConvert.DeserializeObject(jsonFieldMappings);
返回域映射;
}
私有静态动态GetSourceObj()
{
//模拟源对象
var sourceObj=Substitute.For();
sourceObj.dob.Returns(“2011年10月10日”);
sourceObj.ssn.Returns(“555-66-5555”);
sourceObj.sysid.Returns(“9876”);
返回源obj;
}
}//结束程序
公共类目标对象
{
//执行器
公共目标对象()
{ }
公共字符串SSN{get;set;}
公共字符串genu_ID{get;set;}
公共字符串出生日期{get;set;}
公共重写字符串ToString()
{
返回string.Format(“出生日期={0}、\nSSN={1}、\nGEN\u ID={2}”、this.BIRTH\u日期、this.SSN、this.GEN\u ID);
}
}//末级
公共接口ISourceObject
{
字符串ssn{get;set;}
字符串sysid{get;set;}
字符串dob{get;set;}
}
}//结束命名空间

除非您使用的是自动映射库,否则最好的方法就是简单地编写一个函数:

public SecondApiObject ConvertFirstApiObject(FirstApiObject data)
{
     // return a new object with the fields from the first one
}
如果其中有一个
IEnumerable
,则可以使用
Select
调用转换操作:

listOfFirstApiObjects.Select(ConvertFirstApiObject);

如果它始终是IEnumerable,您也可以在
Select
参数中将转换作为lambda内联。

如果FirstApiObject未知怎么办?@DemetriusBerlioz则不可能。如果不知道字段,则无法进行映射。您可以通过反射来检测某些字段,但这样做充其量也将是脆弱的。您可能注意到,也可能没有注意到,我将这个问题标记为“designpattern”。GOF适配器模式不适用于此吗?@DemetriusBerlioz我对这个特定模式还不太熟悉。抱歉:(刚刚看了保罗·金梅尔的书《为C#(第十章)而林克未被释放》,你说的对,布拉德利。