Объединение анонимных типов
Как я могу объединить два анонимных типа, чтобы результат содержал свойства обоих исходных объектов?
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"
// }
Ответы
Ответ 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
};