Created
May 1, 2018 23:50
-
-
Save ajai8085/dffa76134357afe462ed16c23ebb15cd to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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