合并匿名类型

本文关键字:类型 合并 | 更新日期: 2023-09-27 18:02:30

如何合并两个匿名类型,使结果包含两个源对象的属性?

var source1 = new
{
    foo = "foo",
    bar = "bar"
}
var source2 = new
{
    baz = "baz"
}
var merged = Merge(source1, source2) // <-- here's where the magic should happen
// merged: 
// {
//      foo = "foo",
//      bar = "bar",
//      baz = "baz"
// }

合并匿名类型

所以,这是我最后想到的(受@BlueMonkMN的回答的启发):

public dynamic Merge(object item1, object item2)
{
    if (item1 == null || item2 == null)
        return item1 ?? item2 ?? new ExpandoObject();
    dynamic expando = new ExpandoObject();
    var result = expando as IDictionary<string, object>;
    foreach (System.Reflection.PropertyInfo fi in item1.GetType().GetProperties())
    {
        result[fi.Name] = fi.GetValue(item1, null);
    }
    foreach (System.Reflection.PropertyInfo fi in item2.GetType().GetProperties())
    {
        result[fi.Name] = fi.GetValue(item2, null);
    }
    return result;
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Dynamic;
namespace ConsoleApplication1
{
  class Program
  {
     static void Main(string[] args)
     {
        var source1 = new
        {
            foo = "foo",
            bar = "bar"
        };
        var source2 = new
        {
           baz = "baz"
        };
        dynamic merged = Merge(source1, source2);
        Console.WriteLine("{0} {1} {2}", merged.foo, merged.bar, merged.baz);
     }
     static MergedType<T1, T2> Merge<T1, T2>(T1 t1, T2 t2)
     {
        return new MergedType<T1, T2>(t1, t2);
     }
  }
  class MergedType<T1, T2> : DynamicObject
  {
     T1 t1;
     T2 t2;
     Dictionary<string, object> members = new Dictionary<string, object>(StringComparer.InvariantCultureIgnoreCase);
     public MergedType(T1 t1, T2 t2)
     {
        this.t1 = t1;
        this.t2 = t2;
        foreach (System.Reflection.PropertyInfo fi in typeof(T1).GetProperties())
        {
           members[fi.Name] = fi.GetValue(t1, null);
        }
        foreach (System.Reflection.PropertyInfo fi in typeof(T2).GetProperties())
        {
           members[fi.Name] = fi.GetValue(t2, null);
        }
     }
     public override bool TryGetMember(GetMemberBinder binder, out object result)
     {
        string name = binder.Name.ToLower();
        return members.TryGetValue(name, out result);
     }
  }
}

如果您期望的是一个可以以编译时类型安全的方式访问属性的单个对象(而不是在执行时纯动态的结果),则不能这样做。最接近的值是:

var merged = Tuple.Create(source1, source2);
Console.WriteLine(merged.Item1.foo);
Console.WriteLine(merged.Item1.bar);
Console.WriteLine(merged.Item2.baz);
请记住,匿名类型是在编译时创建的。并不是说它们是"动态的"类型。您可以使用。net 4中的ExpandoObject来实现这一点,但它与具有。
中所有相关属性的匿名类型并不完全相同。

下面的代码可以在。net 3.5中工作(可能也可以在2.0中工作)。我修改了davehauser的答案。

    public static object MergeJsonData(object item1, object item2)
    {
        if (item1 == null || item2 == null)
            return item1 ?? item2 ?? new object();
        var result = new Dictionary<string, object>();
        foreach (System.Reflection.PropertyInfo fi in item1.GetType().GetProperties().Where(x => x.CanRead))
        {
            var Value = fi.GetValue(item1, null);
            result[fi.Name] = Value;
        }
        foreach (System.Reflection.PropertyInfo fi in item2.GetType().GetProperties().Where(x => x.CanRead))
        {
            var Value = fi.GetValue(item2, null);
            result[fi.Name] = Value;
        }
        return result;
    }