A musi to być typ anonimowy? Bo jeśli nie, to:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Reflection.Emit;
using System.Threading;
namespace ConsoleOthello
{
// tej nie trzeba pisać, jest już gotowa
internal class JakaśKlasaZEF
{
public string Pole1 { get; set; }
public int Pole2 { get; set; }
}
internal static class HardcoreExtensions
{
private static void AddProperty(TypeBuilder typeBuilder, string name, Type type, PropertyAttributes attriutes)
{
FieldBuilder fb = typeBuilder.DefineField("_" + name, type, FieldAttributes.Private);
MethodBuilder gmb = typeBuilder.DefineMethod("get_" + name, MethodAttributes.Public | MethodAttributes.HideBySig, type, Type.EmptyTypes);
ILGenerator gil = gmb.GetILGenerator();
gil.Emit(OpCodes.Ldarg_0);
gil.Emit(OpCodes.Ldfld, fb);
gil.Emit(OpCodes.Ret);
MethodBuilder smb = typeBuilder.DefineMethod("set_" + name, MethodAttributes.Public | MethodAttributes.HideBySig, null, new Type[] { type });
ILGenerator sil = smb.GetILGenerator();
sil.Emit(OpCodes.Ldarg_0);
sil.Emit(OpCodes.Ldarg_1);
sil.Emit(OpCodes.Stfld, fb);
sil.Emit(OpCodes.Ret);
PropertyBuilder pb = typeBuilder.DefineProperty(name, attriutes, type, new Type[] { type });
pb.SetGetMethod(gmb);
pb.SetSetMethod(smb);
}
public static IEnumerable<dynamic> SelectAndExtend<TSource>(this IEnumerable<TSource> source, object obj)
{
AssemblyBuilder assemblyBuilder = Thread.GetDomain().DefineDynamicAssembly(new AssemblyName("DynamicAsembly"), AssemblyBuilderAccess.Run);
ModuleBuilder moduleBuilder = assemblyBuilder.DefineDynamicModule("DynamicAsembly.dll");
TypeBuilder typeBuilder = moduleBuilder.DefineType("DynamicType", TypeAttributes.Public | TypeAttributes.Class);
var oldProps = typeof(TSource).GetProperties();
foreach (var op in oldProps)
{
AddProperty(typeBuilder, op.Name, op.PropertyType, op.Attributes);
}
var newProps = obj.GetType().GetProperties();
foreach (var np in newProps)
{
AddProperty(typeBuilder, np.Name, np.PropertyType, np.Attributes);
}
Type dynamicType = typeBuilder.CreateType();
var result = new List<dynamic>();
foreach (var s in source)
{
dynamic dob = Activator.CreateInstance(dynamicType);
var props = dynamicType.GetProperties();
for (int i = 0; i < oldProps.Length; i++)
{
var p = props.Single(q => q.Name == oldProps[i].Name);
p.SetValue(dob, oldProps[i].GetValue(s, null), null);
}
for (int i = 0; i < newProps.Length; i++)
{
var p = props.Single(q => q.Name == newProps[i].Name);
p.SetValue(dob, newProps[i].GetValue(obj, null), null);
}
result.Add(dob);
}
return result;
}
}
internal class Program
{
private static void Main(string[] args)
{
var raport = new List<JakaśKlasaZEF> {
new JakaśKlasaZEF { Pole1 = "A", Pole2 = 1, },
new JakaśKlasaZEF { Pole1 = "B", Pole2 = 2, },
new JakaśKlasaZEF { Pole1 = "C", Pole2 = 3, },
new JakaśKlasaZEF { Pole1 = "D", Pole2 = 4, },
};
var temp = raport.SelectAndExtend(new { OPERATOR = "", Cycki = 2 });
foreach (var t in temp)
{
t.OPERATOR = t.Pole1 + t.Pole2;
Console.WriteLine("{0} {1} {2} {3}", t.Pole1, t.Pole2, t.OPERATOR, t.Cycki);
}
Console.ReadLine();
}
}
}
EDIT:
W sumie, to dzięki ExpandoObject
można to napisać krócej i zgrabniej:
public static IEnumerable<dynamic> SelectAndExtend<TSource>(this IEnumerable<TSource> source, object obj)
{
var result = new List<dynamic>();
foreach (var s in source)
{
IDictionary<string, object> newItem = new ExpandoObject();
var sourceProps = s.GetType().GetProperties();
foreach (var sp in sourceProps)
{
newItem[sp.Name] = sp.GetValue(s, null);
}
var anonProps = obj.GetType().GetProperties();
foreach (var ap in anonProps)
{
newItem[ap.Name] = ap.GetValue(obj, null);
}
result.Add((dynamic)newItem);
}
return result;
}