using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Reflection.Emit;
public static void Main(string[] args)
var cliente = new Cliente { Nome = "Alberto", Idade = null, CPF = null, Filhos = 8 };
var endereco = new Endereco { Logradouro = "Rua Alberto", Numero = 123 };
var opa = cliente.Spread(endereco, new { UsaGitHub = true });
foreach (var prop in cliente.GetType().GetProperties())
var valor = prop.GetValue(cliente);
System.Console.WriteLine($"{prop.Name} = {valor}");
public string Nome { get; set; }
public int? Idade { get; set; }
public int? CPF { get; set; }
public int? Filhos { get; set; }
public string Logradouro { get; set; }
public int Numero { get; set; }
public static class Extensions
var assemblyBuilder = AssemblyBuilder.DefineDynamicAssembly(new AssemblyName("AlbertoExcentions"), AssemblyBuilderAccess.RunAndCollect);
ModuleBuilder = assemblyBuilder.DefineDynamicModule("MainModule");
public static object Spread(this object obj, params object[] anotherObject)
var properties = anotherObject
.SelectMany(o => o.GetType().GetProperties(), (o, p) => (o: o, p: p))
.ToDictionary(t => t.p.Name, t => (propName: t.p.Name, propType: t.p.PropertyType, propValue: t.p.GetValue(t.o)));
var objType = CreateClass(properties);
var finalObj = Activator.CreateInstance(objType);
foreach (var prop in objType.GetProperties())
prop.SetValue(finalObj, properties[prop.Name].propValue);
const MethodAttributes METHOD_ATTRIBUTES = MethodAttributes.Public | MethodAttributes.SpecialName | MethodAttributes.HideBySig;
private static ModuleBuilder ModuleBuilder;
internal static Type CreateClass(IDictionary<string, (string propName, Type type, object)> parameters)
var typeBuilder = ModuleBuilder.DefineType(Guid.NewGuid().ToString(), TypeAttributes.Public | TypeAttributes.Class | TypeAttributes.AutoClass | TypeAttributes.AnsiClass | TypeAttributes.BeforeFieldInit | TypeAttributes.AutoLayout, null);
typeBuilder.DefineDefaultConstructor(MethodAttributes.Public | MethodAttributes.SpecialName | MethodAttributes.RTSpecialName);
foreach (var parameter in parameters)
CreateProperty(typeBuilder, parameter.Key, parameter.Value.type);
var type = typeBuilder.CreateTypeInfo().AsType();
private static PropertyBuilder CreateProperty(TypeBuilder typeBuilder, string propertyName, Type propertyType)
var fieldBuilder = typeBuilder.DefineField("_" + propertyName, propertyType, FieldAttributes.Private);
var propBuilder = typeBuilder.DefineProperty(propertyName, PropertyAttributes.HasDefault, propertyType, null);
propBuilder.SetGetMethod(DefineGet(typeBuilder, fieldBuilder, propBuilder));
propBuilder.SetSetMethod(DefineSet(typeBuilder, fieldBuilder, propBuilder));
private static MethodBuilder DefineSet(TypeBuilder typeBuilder, FieldBuilder fieldBuilder, PropertyBuilder propBuilder)
=> DefineMethod(typeBuilder, $"set_{propBuilder.Name}", null, new[] { propBuilder.PropertyType }, il =>
il.Emit(OpCodes.Ldarg_0);
il.Emit(OpCodes.Ldarg_1);
il.Emit(OpCodes.Stfld, fieldBuilder);
private static MethodBuilder DefineGet(TypeBuilder typeBuilder, FieldBuilder fieldBuilder, PropertyBuilder propBuilder)
=> DefineMethod(typeBuilder, $"get_{propBuilder.Name}", propBuilder.PropertyType, Type.EmptyTypes, il =>
il.Emit(OpCodes.Ldarg_0);
il.Emit(OpCodes.Ldfld, fieldBuilder);
private static MethodBuilder DefineMethod(TypeBuilder typeBuilder, string methodName, Type propertyType, Type[] parameterTypes, Action<ILGenerator> bodyWriter)
var methodBuilder = typeBuilder.DefineMethod(methodName, METHOD_ATTRIBUTES, propertyType, parameterTypes);
bodyWriter(methodBuilder.GetILGenerator());