ホームページ  >  記事  >  バックエンド開発  >  C#の動的型と動的オブジェクトの作成、2つのオブジェクトのマージ、およびマップのサンプルコードの詳細な説明

C#の動的型と動的オブジェクトの作成、2つのオブジェクトのマージ、およびマップのサンプルコードの詳細な説明

黄舟
黄舟オリジナル
2017-03-21 11:57:312379ブラウズ

次のエディターは、記事 c#動的タイプ、および動的オブジェクトの作成、2 つのオブジェクトの結合、およびマップ インスタンスを提供します。編集者はこれがとても良いと思ったので、参考として共有します。編集者をフォローして見てみましょう

クライアントからリクエストされたデータに応答するとき、たとえばデータベース内のデータが int 型であるなど、データを処理する必要がある場合があります。列挙、またはその他の論理的な意味 (データベースの設計はデータ セキュリティ、ストレージ容量などの観点から行われる場合があります) ですが、その特定の意味はクライアントに表示される必要があります。

この時の処理方法は一般的に2です。複雑で単一のロジックでない場合は、SQL文を直接変更することでデータソースを処理できます。このとき、コード内で何も処理する必要はありません。

しかし、ロジックが少し複雑だったり、判断状況に分岐が多かったりする場合は、コードの観点から対処する必要があります。単一のオブジェクトは問題ありませんが、リスト8742468051c85b06f0a0af9e3e506b5c など複数のオブジェクトがある場合は、特定のオブジェクトのフィールドで XXX をループする必要があります。 その後、Arg の中間オブジェクトである DTO が登場しました。もちろん、私はこのデザインが個人的に気に入っていますが、時々めんどくさいので書きたくないことがあります (ほとんどの場合、量産用のコード ジェネレーターを直接書きます)。 ) たとえば、テストするとき、個人的な作業を行うとき、デモンストレーションを行うとき、目的の効果をすぐに提示するだけでは、面倒なので、市場には次のようなマップ ライブラリがあまりないと言うでしょう。 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 オブジェクトを変更することもできます

以下のテストを作成し、それを

expression

tree に変更するのが最適ですまずコード

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つのオブジェクトのマージ、およびマップのサンプルコードの詳細な説明の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。