当前位置: 移动技术网 > IT编程>开发语言>c# > c#动态类型,及动态对象的创建,合并2个对象,map实例

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

2019年07月18日  | 移动技术网IT编程  | 我要评论

经常会遇到这样的情况,我们在响应客户端请求的数据的时候需要对数据进行处理,比如数据库中的数据是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实例就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持移动技术网。

如对本文有疑问, 点击进行留言回复!!

相关文章:

验证码:
移动技术网