Подтвердить что ты не робот

Объединение анонимных типов

Как я могу объединить два анонимных типа, чтобы результат содержал свойства обоих исходных объектов?

var source1 = new
{
    foo = "foo",
    bar = "bar"
}

var source2 = new
{
    baz = "baz"
}

var merged = Merge(source1, source2) // <-- here where the magic should happen

// merged: 
// {
//      foo = "foo",
//      bar = "bar",
//      baz = "baz"
// }
4b9b3361

Ответ 1

Итак, вот что я, наконец, придумал (вдохновленный ответом @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;
}

Ответ 2

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);
     }
  }
}

Ответ 3

Вы не можете. Ближе всего вы могли бы прийти:

var merged = Tuple.Create(source1, source2);

Console.WriteLine(merged.Item1.foo);
Console.WriteLine(merged.Item1.bar);
Console.WriteLine(merged.Item2.baz);

Имейте в виду, что анонимные типы создаются во время компиляции. Это не похоже на "динамические" типы. Вы можете использовать ExpandoObject в .NET 4 для этого, но это не совсем то же самое, что анонимный тип со всеми соответствующими свойствами.

Ответ 4

В .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;
    }

Ответ 5

     var merged = new
     {
        source1 = source1,
        source2 = source2
     };

или

     var merged2 = new
     {
        foo = source1.foo,
        bar = source1.bar,
        baz = source2.baz
     };