Skip to content

Instantly share code, notes, and snippets.

@DCCoder90
Created December 6, 2018 21:50
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save DCCoder90/2ef3d87a1ee217d4032cc9b423d5aa3d to your computer and use it in GitHub Desktop.
Save DCCoder90/2ef3d87a1ee217d4032cc9b423d5aa3d to your computer and use it in GitHub Desktop.
Creates objects at runtime to store information
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