Skip to content

Instantly share code, notes, and snippets.

@ajai8085
Created May 1, 2018 23:50
Show Gist options
  • Save ajai8085/dffa76134357afe462ed16c23ebb15cd to your computer and use it in GitHub Desktop.
Save ajai8085/dffa76134357afe462ed16c23ebb15cd to your computer and use it in GitHub Desktop.
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Dynamic;
using System.Linq;
using System.Reflection;
using System.Reflection.Emit;
using System.Text;
using System.Threading.Tasks;
namespace ConsoleApp1
{
class Program
{
static void Main(string[] args)
{
var ano = new {Name = "ajai", LName = "dsfkjdkljf"};
var ano2 = new {Name2 = "first name2", LName2 = "dsfkjdkljf2"};
var v = MergeObjects(ano, ano2);
dynamic d = v;
if (d.Name != ano.Name)
{
throw new Exception("Merge object failed");
}
if (d.Name2 != ano2.Name2)
{
throw new Exception("Merge object failed");
}
if (d.LName != ano.LName)
{
throw new Exception("Merge object failed");
}
if (d.LName2 != ano2.LName2)
{
throw new Exception("Merge object failed");
}
}
/// <summary>
/// Merges the objects.
/// </summary>
/// <param name="item1">The item1.</param>
/// <param name="item2">The item2.</param>
/// <returns></returns>
/// <exception cref="ArgumentNullException">
/// item1
/// or
/// item2
/// or
/// item2
/// </exception>
/// <exception cref="NullReferenceException"></exception>
public static object MergeObjects(object item1, object item2) //Should not contain matching properties
{
if (item1 == null)
{
throw new ArgumentNullException($"Invalid argument {nameof(item1)}");
}
if (item2 == null)
{
throw new ArgumentNullException($"Invalid argument {nameof(item2)}");
}
var item1Props = item1.GetType().GetProperties().Where(x => x.CanRead).ToList();
var item2Props = item2.GetType().GetProperties().Where(x => x.CanRead).ToList();
var namesItem1 = item1Props.Select(i => i.Name);
if (item2Props.Any(i => namesItem1.Contains(i.Name)))
{
throw new ArgumentNullException(
$"Matching property names found {nameof(item2)} {nameof(item2)}. Use unique property names");
}
var name = $"MyAsm{Guid.NewGuid()}";
var dynamicAssemblyName = new AssemblyName(name);
var dynamicAssembly = AssemblyBuilder.DefineDynamicAssembly(dynamicAssemblyName, AssemblyBuilderAccess.Run);
var dynamicModule = dynamicAssembly.DefineDynamicModule(name);
var dynamicAnonymousType = dynamicModule.DefineType("MyAnon" + Guid.NewGuid(), TypeAttributes.Public);
//TODO:: Zip the list
foreach (var fi in item1Props)
{
CreateProperty(dynamicAnonymousType, fi.Name, fi.PropertyType);
}
foreach (var fi in item2Props)
{
CreateProperty(dynamicAnonymousType, fi.Name, fi.PropertyType);
}
// Return the type to the caller
var typeInstance = dynamicAnonymousType.CreateType();
var instance = Activator.CreateInstance(typeInstance);
foreach (var fi in item1Props)
{
var value = fi.GetValue(item1, null);
var dest = typeInstance.GetProperty(fi.Name);
dest.SetValue(instance, value); // should throw null ref exception
}
foreach (var fi in item2Props)
{
var value = fi.GetValue(item2, null);
var dest = typeInstance.GetProperty(fi.Name);
dest.SetValue(instance, value); // should throw null ref exception
}
return instance;
}
private static PropertyBuilder CreateProperty(TypeBuilder tb, string propertyName, Type propertyType)
{
var fieldBuilder = tb.DefineField("_" + propertyName, propertyType, FieldAttributes.Private);
var propertyBuilder = tb.DefineProperty(propertyName, PropertyAttributes.HasDefault, propertyType, null);
var getPropMthdBldr = tb.DefineMethod("get_" + propertyName,
MethodAttributes.Public | MethodAttributes.SpecialName | MethodAttributes.HideBySig, propertyType,
Type.EmptyTypes);
var getIl = getPropMthdBldr.GetILGenerator();
getIl.Emit(OpCodes.Ldarg_0);
getIl.Emit(OpCodes.Ldfld, fieldBuilder);
getIl.Emit(OpCodes.Ret);
var setPropMthdBldr =
tb.DefineMethod("set_" + propertyName,
MethodAttributes.Public |
MethodAttributes.SpecialName |
MethodAttributes.HideBySig,
null, new[] {propertyType});
var setIl = setPropMthdBldr.GetILGenerator();
var modifyProperty = setIl.DefineLabel();
var exitSet = setIl.DefineLabel();
setIl.MarkLabel(modifyProperty);
setIl.Emit(OpCodes.Ldarg_0);
setIl.Emit(OpCodes.Ldarg_1);
setIl.Emit(OpCodes.Stfld, fieldBuilder);
setIl.Emit(OpCodes.Nop);
setIl.MarkLabel(exitSet);
setIl.Emit(OpCodes.Ret);
propertyBuilder.SetGetMethod(getPropMthdBldr);
propertyBuilder.SetSetMethod(setPropMthdBldr);
return propertyBuilder;
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment