c#動(dòng)態(tài)類型,及動(dòng)態(tài)對(duì)象的創(chuàng)建,合并2個(gè)對(duì)象,map實(shí)例
經(jīng)常會(huì)遇到這樣的情況,我們?cè)陧憫?yīng)客戶端請(qǐng)求的數(shù)據(jù)的時(shí)候需要對(duì)數(shù)據(jù)進(jìn)行處理,比如數(shù)據(jù)庫(kù)中的數(shù)據(jù)是int型,它可能表示某個(gè)枚舉,或者其它的邏輯意義(數(shù)據(jù)庫(kù)這樣的設(shè)計(jì)可能是從數(shù)據(jù)安全性、存儲(chǔ)量上等角度考慮),但是客戶端顯示的時(shí)候需要是它具體的意義。
這個(gè)時(shí)候我們的處理方式一般都是2中的,如果邏輯不復(fù)雜,且單一的話,直接修改sql語(yǔ)句就能處理好數(shù)據(jù)源,這個(gè)時(shí)候代碼里面不需要處理什么。
但是如果邏輯復(fù)稍許復(fù)雜或者判斷的情況有很多分支,我們不得不從代碼角度來(lái)處理了。單個(gè)對(duì)象還好,多個(gè)對(duì)象比如是個(gè)list<T>,那就要循環(huán)對(duì)某個(gè)對(duì)象的字段進(jìn)行XXX了。
進(jìn)而衍生出了這就出現(xiàn)了DTO,Arg的中間對(duì)象,當(dāng)然,我個(gè)人是很喜歡這樣的設(shè)計(jì)的,但是某些時(shí)候也會(huì)偷懶不想寫(多半情況我直接寫代碼生器批量生產(chǎn)),比如在測(cè)試的時(shí)候,在接私活的時(shí)候,在演示的時(shí)候,只為快速呈現(xiàn)想要的效果 都懶得去屑,是的,你會(huì)說(shuō)市面上不是有很多的map庫(kù),比如automap,tinymap,甚至json.net里面的動(dòng)態(tài)特性重寫,方法當(dāng)然很多,但用一個(gè)大輪子來(lái)費(fèi)力搞這么個(gè)小事,我覺得劃不來(lái)。且輪子越來(lái)越大它要干的事越多,我可不想搞的那么復(fù)雜,嗯,就是這樣,寫了個(gè)。
具體的代碼貼到下面,如果看明白,會(huì)很方便的擴(kuò)展了或修改成自己想要的效果。
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>
/// 支持動(dòng)態(tài)輸出的對(duì)象接口
/// </summary>
public interface IInjectClass
{
}
/// <summary>
/// 動(dòng)態(tài)輸出時(shí)忽略此標(biāo)記的屬性
/// </summary>
public class IngorePropertyAttribute : Attribute
{
}
下面我們測(cè)試一個(gè):
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);
您可以重新構(gòu)造帶參數(shù)的特性或者修改injectAct對(duì)象,改成適合自己的
下面寫個(gè)測(cè)試,改成表達(dá)式樹最好了,先上個(gè)碼
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>
/// 單個(gè)對(duì)象映射
/// </summary>
/// <typeparam name="T">類型</typeparam>
/// <param name="source">實(shí)例</param>
/// <param name="injectAct">map方法集</param>
/// <returns>映射后的動(dòng)態(tài)對(duì)象</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; //原來(lái)是屬性名
var _value = p.GetValue(source, null); //原來(lái)的屬性值
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個(gè)對(duì)象
/// </summary>
/// <typeparam name="TSource">對(duì)象1類型</typeparam>
/// <typeparam name="TTarget">對(duì)象2類型</typeparam>
/// <param name="s">對(duì)象1實(shí)例</param>
/// <param name="t">對(duì)象2實(shí)例</param>
/// <returns>合并后的動(dòng)態(tài)對(duì)象</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個(gè)對(duì)象
/// </summary>
/// <typeparam name="TSource">對(duì)象1類型</typeparam>
/// <typeparam name="TTarget">對(duì)象2類型</typeparam>
/// <param name="s">對(duì)象1實(shí)例</param>
/// <param name="t">對(duì)象2實(shí)例</param>
/// <returns>合并后的動(dòng)態(tài)對(duì)象</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;
}
}
}
測(cè)試一下:
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#動(dòng)態(tài)類型,及動(dòng)態(tài)對(duì)象的創(chuàng)建,合并2個(gè)對(duì)象,map實(shí)例就是小編分享給大家的全部?jī)?nèi)容了,希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。
相關(guān)文章
淺析C#?AsyncLocal如何在異步間進(jìn)行數(shù)據(jù)流轉(zhuǎn)
在異步編程中,處理異步操作之間的數(shù)據(jù)流轉(zhuǎn)是一個(gè)比較常用的操作,C#異步編程提供了一個(gè)強(qiáng)大的工具來(lái)解決這個(gè)問(wèn)題,那就是AsyncLocal,下面我們就來(lái)看看AsyncLocal的原理和用法吧2023-08-08
Python設(shè)計(jì)模式編程中的備忘錄模式與對(duì)象池模式示例
這篇文章主要介紹了Python設(shè)計(jì)模式編程中的備忘錄模式與對(duì)象池模式,文中分別舉了表單和線程的相關(guān)示例,需要的朋友可以參考下2016-02-02
C#獲取HTML文本的第一張圖片與截取內(nèi)容摘要示例代碼
在日常web開發(fā)的時(shí)候,經(jīng)常會(huì)遇到需要獲取保存的HTML文本中的第一張圖片,并且截取內(nèi)容摘要的效果,例如織夢(mèng)的后臺(tái)添加完詳細(xì)內(nèi)容后就是自動(dòng)讀取內(nèi)容摘要,并保存第一張圖片為縮略圖,那么這篇文章跟大家分享下利用C#如何實(shí)現(xiàn),感興趣的朋友們下面來(lái)一起看看吧。2016-10-10
C#導(dǎo)出生成excel文件的方法小結(jié)(xml,html方式)
C#導(dǎo)出生成excel文件的方法小結(jié)(xml,html方式)。需要的朋友可以過(guò)來(lái)參考下,希望對(duì)大家有所幫助2013-10-10
C#中的高效IO庫(kù)System.IO.Pipelines
這篇文章介紹了C#中的高效IO庫(kù)System.IO.Pipelines,文中通過(guò)示例代碼介紹的非常詳細(xì)。對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2022-07-07
c# GridControl的模糊查詢實(shí)現(xiàn)代碼
這篇文章主要介紹了c# GridControl的模糊查詢實(shí)現(xiàn)代碼,需要的朋友可以參考下2017-02-02

