Created
December 6, 2018 21:50
-
-
Save DCCoder90/2ef3d87a1ee217d4032cc9b423d5aa3d to your computer and use it in GitHub Desktop.
Creates objects at runtime to store information
This file contains hidden or 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.Reflection; | |
using System.Reflection.Emit; | |
namespace EntityBuilder | |
{ | |
internal class EntityBuilder | |
{ | |
private readonly IDictionary<string, Type> _cache; | |
public EntityBuilder() | |
{ | |
_cache = new Dictionary<string, Type>(); | |
} | |
public Type CreateNewObject(string typeName, IDictionary<string, Type> propertyDefinitions) | |
{ | |
if (_cache.ContainsKey(typeName)) | |
return _cache[typeName]; | |
return CompileResultType(typeName, propertyDefinitions); | |
} | |
public Type CreateNewObject(string typeName, string[] properties) | |
{ | |
if (_cache.ContainsKey(typeName)) | |
return _cache[typeName]; | |
var propertyDefinitions = propertyNameToStringDefinition(properties); | |
return CompileResultType(typeName, propertyDefinitions); | |
} | |
private IDictionary<string, Type> propertyNameToStringDefinition(string[] properties) | |
{ | |
var dict = new Dictionary<string, Type>(); | |
foreach (var property in properties) dict.Add(property, typeof(string)); | |
return dict; | |
} | |
private Type CompileResultType(string typeName, IDictionary<string, Type> properties) | |
{ | |
var tb = GetTypeBuilder(typeName); | |
var constructor = | |
tb.DefineDefaultConstructor(MethodAttributes.Public | MethodAttributes.SpecialName | | |
MethodAttributes.RTSpecialName); | |
foreach (var field in properties) | |
CreateProperty(tb, field.Key, field.Value); | |
var objectType = tb.CreateType(); | |
_cache.Add(typeName, objectType); | |
return objectType; | |
} | |
private TypeBuilder GetTypeBuilder(string typeName) | |
{ | |
var typeSignature = typeName; | |
var an = new AssemblyName(typeSignature); | |
var assemblyBuilder = AppDomain.CurrentDomain.DefineDynamicAssembly(an, AssemblyBuilderAccess.Run); | |
var moduleBuilder = assemblyBuilder.DefineDynamicModule("MainModule"); | |
var tb = moduleBuilder.DefineType(typeSignature, | |
TypeAttributes.Public | | |
TypeAttributes.Class | | |
TypeAttributes.AutoClass | | |
TypeAttributes.AnsiClass | | |
TypeAttributes.BeforeFieldInit | | |
TypeAttributes.AutoLayout, | |
null); | |
return tb; | |
} | |
private void 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); | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment