好得很程序员自学网

<tfoot draggable='sEl'></tfoot>

c#动态类型,及动态对象的创建,合并2个对象,map实例

经常会遇到这样的情况,我们在响应客户端请求的数据的时候需要对数据进行处理,比如数据库中的数据是int型,它可能表示某个枚举,或者其它的逻辑意义(数据库这样的设计可能是从数据安全性、存储量上等角度考虑),但是客户端显示的时候需要是它具体的意义。

这个时候我们的处理方式一般都是2中的,如果逻辑不复杂,且单一的话,直接修改sql语句就能处理好数据源,这个时候代码里面不需要处理什么。

但是如果逻辑复稍许复杂或者判断的情况有很多分支,我们不得不从代码角度来处理了。单个对象还好,多个对象比如是个list<T>,那就要循环对某个对象的字段进行XXX了。

进而衍生出了这就出现了DTO,Arg的中间对象,当然,我个人是很喜欢这样的设计的,但是某些时候也会偷懒不想写(多半情况我直接写代码生器批量生产),比如在测试的时候,在接私活的时候,在演示的时候,只为快速呈现想要的效果 都懒得去屑,是的,你会说市面上不是有很多的map库,比如automap,tinymap,甚至json.net里面的动态特性重写,方法当然很多,但用一个大轮子来费力搞这么个小事,我觉得划不来。且轮子越来越大它要干的事越多,我可不想搞的那么复杂,嗯,就是这样,写了个。

具体的代码贴到下面,如果看明白,会很方便的扩展了或修改成自己想要的效果。

?

using System.Dynamic;

using System.Reflection;

using System.Collections.Concurrent;

 

private static readonly ConcurrentDictionary<RuntimeTypeHandle, PropertyInfo[]>

   DynamicObjectProperties = new ConcurrentDictionary<RuntimeTypeHandle, PropertyInfo[]>();

 

private IDictionary<string, Object> ToDynamicResult<T>(T classobj, Func<string, object, object> injectAct)

   where T : IInjectClass, new ()

{

   var type = typeof (T);

   var key = type.TypeHandle;

   var dynamicResult = new ExpandoObject() as IDictionary<string, Object>;

 

   PropertyInfo[] queryPts = null ;

   DynamicObjectProperties.TryGetValue(key, out queryPts);

 

   if (queryPts == null )

   {

     queryPts = type.GetProperties();

     DynamicObjectProperties.TryAdd(key, queryPts);

   }

 

   foreach ( var p in queryPts)

   {

     var attributes = p.GetCustomAttributes( typeof (IngorePropertyAttribute), true );

     var columnMapping = attributes.FirstOrDefault();

     if (columnMapping != null ) continue ;

 

     var _name = p.Name;

     var _value = p.GetValue(classobj, null );

     object _tempvalue = _value;

 

     if (injectAct != null ) _tempvalue = injectAct.Invoke(_name, _value);

 

     //var value = Convert.ChangeType(value,typeof(string));

     dynamicResult.Add(p.Name, _tempvalue);

   }

 

   return dynamicResult;

}

 

/// <summary>

/// 支持动态输出的对象接口

/// </summary>

public interface IInjectClass

{

}

/// <summary>

/// 动态输出时忽略此标记的属性

/// </summary>

public class IngorePropertyAttribute : Attribute

{

}

下面我们测试一个:

?

public class kk : IInjectClass

  {

   public string aa { get; set; }

   public int bb { get; set; }

   [IngoreProperty]

   public bool cc { get; set; }

   public DateTime dd { get; set; }

  }kk ist = new kk();

ist.aa = "aaa" ;

ist.bb = 123;

ist.cc = false ;

ist.dd = DateTime.Now;

 

var tt = ToDynamicResult<kk>(ist, (k, v) =>

{

   if (k != "aa" ) return v;

 

   return v + "(改变了哦)" ;

});

 

var json = Tools.JsonUtils.JsonSerializer(tt);

 

json = json + "<br /><br />" + Tools.JsonUtils.JsonSerializer(ToDynamicResult<kk>(

     new kk

     {

       aa = "test" ,

       bb = 789,

       cc = true ,

       dd = DateTime.Now.AddDays(2)

     }, null ));

 

Response.Write(json);

您可以重新构造带参数的特性或者修改injectAct对象,改成适合自己的

下面写个测试,改成表达式树最好了,先上个码

?

using System;

using System.Linq;

using System.Dynamic;

using System.Reflection;

using System.Linq.Expressions;

using System.Collections.Generic;

using System.Collections.Concurrent;

 

namespace Tools

{

   public class Class2Map

   {

     private static readonly ConcurrentDictionary<RuntimeTypeHandle, PropertyInfo[]>

       DynamicObjectProperties = new ConcurrentDictionary<RuntimeTypeHandle, PropertyInfo[]>();

 

     private static PropertyInfo[] GetObjectProperties<T>()

     {

       var type = typeof (T);

       var key = type.TypeHandle;

       PropertyInfo[] queryPts = null ;

 

       DynamicObjectProperties.TryGetValue(key, out queryPts);

 

       if (queryPts == null )

       {

         queryPts = type.GetProperties();

         DynamicObjectProperties.TryAdd(key, queryPts);

       }

 

       return queryPts;

     }

 

     /// <summary>

     /// 单个对象映射

     /// </summary>

     /// <typeparam name="T">类型</typeparam>

     /// <param name="source">实例</param>

     /// <param name="injectAct">map方法集</param>

     /// <returns>映射后的动态对象</returns>

     public static IDictionary<string, Object> DynamicResult<T>(T source, params MapCondition[] injectAct) //where T : ICustomMap

     {

       var queryPts = GetObjectProperties<T>();

       var dynamicResult = new ExpandoObject() as IDictionary<string, Object>;

 

       foreach ( var p in queryPts)

       {

         var attributes = p.GetCustomAttributes( typeof (IngoreProperty), true );

         if (attributes.FirstOrDefault() != null ) continue ;

 

         var _name = p.Name;           //原来是属性名

         var _value = p.GetValue(source, null ); //原来的属性值

         object _resultvalue = _value;      //最终的映射值

 

         if (injectAct != null )

         {

           string _tempname = null ;

           var condition = injectAct.FirstOrDefault(x => x.Orginal == _name);

           if (CheckChangeInfo(condition, out _tempname))

           {

             _resultvalue = condition.fn.Invoke(_value);

             dynamicResult.Add(_tempname ?? _name, _resultvalue);

             continue ;

           }

         }

 

         //var value = Convert.ChangeType(value,typeof(string));

         dynamicResult.Add(_name, _resultvalue);

       }

 

       return dynamicResult;

     }

 

     /// <summary>

     /// 合并2个对象

     /// </summary>

     /// <typeparam name="TSource">对象1类型</typeparam>

     /// <typeparam name="TTarget">对象2类型</typeparam>

     /// <param name="s">对象1实例</param>

     /// <param name="t">对象2实例</param>

     /// <returns>合并后的动态对象</returns>

     public static IDictionary<string, Object> MergerObject<TSource, TTarget>(TSource s, TTarget t)

     {

       var targetPts = GetObjectProperties<TSource>();

 

       PropertyInfo[] mergerPts = null ;

       var _type = t.GetType();

       mergerPts = _type.Name.Contains( "<>" ) ? _type.GetProperties() : GetObjectProperties<TTarget>();

 

       var dynamicResult = new ExpandoObject() as IDictionary<string, Object>;

 

       foreach ( var p in targetPts)

       {

         var attributes = p.GetCustomAttributes( typeof (IngoreProperty), true );

         if (attributes.FirstOrDefault() != null ) continue ;

 

         dynamicResult.Add(p.Name, p.GetValue(s, null ));

       }

       foreach ( var p in mergerPts)

       {

         var attributes = p.GetCustomAttributes( typeof (IngoreProperty), true );

         if (attributes.FirstOrDefault() != null ) continue ;

 

         dynamicResult.Add(p.Name, p.GetValue(t, null ));

       }

 

       return dynamicResult;

     }

     /// <summary>

     /// 合并2个对象

     /// </summary>

     /// <typeparam name="TSource">对象1类型</typeparam>

     /// <typeparam name="TTarget">对象2类型</typeparam>

     /// <param name="s">对象1实例</param>

     /// <param name="t">对象2实例</param>

     /// <returns>合并后的动态对象</returns>

     public static List<IDictionary<string, Object>> MergerListObject<TSource, TTarget>(List<TSource> s, TTarget t)

     {

       var targetPts = GetObjectProperties<TSource>();

 

       PropertyInfo[] mergerPts = null ;

       var _type = t.GetType();

       mergerPts = _type.Name.Contains( "<>" ) ? _type.GetProperties() : GetObjectProperties<TTarget>();

 

       var result = new List<IDictionary<string, Object>>();

 

       s.ForEach(x =>

       {

         var dynamicResult = new ExpandoObject() as IDictionary<string, Object>;

 

         foreach ( var p in targetPts)

         {

           var attributes = p.GetCustomAttributes( typeof (IngoreProperty), true );

           if (attributes.FirstOrDefault() != null ) continue ;

 

           dynamicResult.Add(p.Name, p.GetValue(x, null ));

         }

 

         foreach ( var p in mergerPts)

         {

           var attributes = p.GetCustomAttributes( typeof (IngoreProperty), true );

           if (attributes.FirstOrDefault() != null ) continue ;

 

           dynamicResult.Add(p.Name, p.GetValue(t, null ));

         }

 

         result.Add(dynamicResult);

       });

 

       return result;

     }

 

     private static bool CheckChangeInfo(MapCondition condition, out string name)

     {

       name = null ;

 

       bool result = condition != null &&

              condition.fn != null &&

              !string.IsNullOrWhiteSpace(condition.Orginal); //&&

             //!string.IsNullOrWhiteSpace(condition.NewName);

 

       if (result)

       {

         var temp = condition.NewName;

         name = (string.IsNullOrWhiteSpace(temp) || temp.Trim().Length == 0) ? null : temp;

       }

 

       return result;

     }

   }

}

测试一下:

?

List<KeyValue> kk = new List<KeyValue>

{

   new KeyValue{key= "aaa" , value= "111" },

   new KeyValue{key= "bbb" , value= "222" },

   new KeyValue{key= "ccc" , value= "333" },

   new KeyValue{key= "ddd" , value= "444" },

};

 

var result = Class2Map.MergerListObject<KeyValue, dynamic>(kk, new { p = "jon test" });

var json = JsonUtils.JsonSerializer(result);

 

Response.Write(json);

输出如下:

?

[{ "key" : "aaa" , "value" : "111" , "p" : "jon test" },{ "key" : "bbb" , "value" : "222" , "p" : "jon test" },{ "key" : "ccc" , "value" : "333" , "p" : "jon test" },{ "key" : "ddd" , "value" : "444" , "p" : "jon test" }]

 

var result = Class2Map.MergerObject<KeyValue, dynamic>(

         new KeyValue { key = "aaa" , value = "111" },

         new { p = "jon test" }

       );

var json = JsonUtils.JsonSerializer(result);

 

Response.Write(json);

输出如下:

?

{ "key" : "aaa" , "value" : "111" , "p" : "jon test" }

以上这篇c#动态类型,及动态对象的创建,合并2个对象,map实例就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持服务器之家。

dy("nrwz");

查看更多关于c#动态类型,及动态对象的创建,合并2个对象,map实例的详细内容...

  阅读:41次