Skip to content

Instantly share code, notes, and snippets.

@regionbbs
Created April 3, 2013 05:45
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 regionbbs/25d609730d3d4ab3a1d8 to your computer and use it in GitHub Desktop.
Save regionbbs/25d609730d3d4ab3a1d8 to your computer and use it in GitHub Desktop.
TableOperationUtil class
public class TableOperationUtil
{
private static IDictionary<string, Type> EntityTypeDictionary = new Dictionary<string, Type>();
public static TableOperation Insert(object Entity)
{
return TableOperation.Insert(CreateDynamicEntity(Entity));
}
public static TableOperation Insert(object Entity, string PartitionKey, string RowKey)
{
ITableEntity entity = CreateDynamicEntity(Entity);
entity.PartitionKey = PartitionKey;
entity.RowKey = RowKey;
return TableOperation.Insert(entity);
}
public static TableOperation InsertOrReplace(object Entity)
{
return TableOperation.InsertOrMerge(CreateDynamicEntity(Entity));
}
public static TableOperation InsertOrReplace(object Entity, string PartitionKey, string RowKey)
{
ITableEntity entity = CreateDynamicEntity(Entity);
entity.PartitionKey = PartitionKey;
entity.RowKey = RowKey;
return TableOperation.InsertOrReplace(entity);
}
public static TableOperation InsertOrMerge(object Entity)
{
return TableOperation.InsertOrMerge(CreateDynamicEntity(Entity));
}
public static TableOperation InsertOrMerge(object Entity, string PartitionKey, string RowKey)
{
ITableEntity entity = CreateDynamicEntity(Entity);
entity.PartitionKey = PartitionKey;
entity.RowKey = RowKey;
return TableOperation.InsertOrMerge(entity);
}
public static TableOperation Replace(object Entity)
{
return TableOperation.Replace(CreateDynamicEntity(Entity));
}
public static TableOperation Replace(object Entity, string PartitionKey, string RowKey)
{
ITableEntity entity = CreateDynamicEntity(Entity);
entity.PartitionKey = PartitionKey;
entity.RowKey = RowKey;
return TableOperation.Replace(entity);
}
public static TableOperation Merge(object Entity)
{
return TableOperation.Merge(CreateDynamicEntity(Entity));
}
public static TableOperation Merge(object Entity, string PartitionKey, string RowKey)
{
ITableEntity entity = CreateDynamicEntity(Entity);
entity.PartitionKey = PartitionKey;
entity.RowKey = RowKey;
return TableOperation.Merge(entity);
}
public static TableOperation Delete(object Entity)
{
return TableOperation.Delete(CreateDynamicEntity(Entity));
}
public static TableOperation Delete(object Entity, string PartitionKey, string RowKey)
{
ITableEntity entity = CreateDynamicEntity(Entity);
entity.PartitionKey = PartitionKey;
entity.RowKey = RowKey;
return TableOperation.Delete(entity);
}
private static ITableEntity CreateDynamicEntity(object AnonymousObject)
{
if (AnonymousObject == null)
return null;
// check property map.
PropertyInfo[] properties = AnonymousObject.GetType().GetProperties();
IEnumerable<PropertyInfo> typeProperties = null;
Type objectType = null;
bool typeFound = false;
foreach (KeyValuePair<string, Type> type in EntityTypeDictionary)
{
typeProperties = type.Value.GetProperties().Where(c => c.DeclaringType == type.Value);
int propertyMatchedCount = 0;
foreach (PropertyInfo property in properties)
{
if (property.DeclaringType == AnonymousObject.GetType())
{
var q = from p in typeProperties
where p.Name == property.Name && p.PropertyType == property.PropertyType
select p;
if (q.Count() == 1)
propertyMatchedCount++;
}
}
if (propertyMatchedCount == properties.Where(c => c.DeclaringType == AnonymousObject.GetType()).Count())
{
typeFound = true;
objectType = type.Value;
}
if (typeFound)
break;
}
if (!typeFound)
{
objectType = CreateType(AnonymousObject);
typeProperties = objectType.GetProperties().Where(c => c.DeclaringType == objectType);
}
object o = Activator.CreateInstance(objectType);
// apply value.
foreach (PropertyInfo property in properties)
{
if (property.DeclaringType == AnonymousObject.GetType())
{
var q = from p in typeProperties
where p.Name == property.Name && p.PropertyType == property.PropertyType
select p;
q.First().SetValue(o, property.GetValue(AnonymousObject, null));
}
}
ITableEntity entity = o as ITableEntity;
if (properties.Where(c => c.Name == "PartitionKey").Count() > 0)
entity.PartitionKey = properties.Where(c => c.Name == "PartitionKey").First().GetValue(AnonymousObject, null).ToString();
if (properties.Where(c => c.Name == "RowKey").Count() > 0)
entity.RowKey = properties.Where(c => c.Name == "RowKey").First().GetValue(AnonymousObject, null).ToString();
return (ITableEntity)o;
}
private static Type CreateType(object AnonymousObject)
{
Random rnd = new Random();
int typeRandomNumber = 0;
do
{
typeRandomNumber = rnd.Next(1000000, 9999999);
} while (EntityTypeDictionary.ContainsKey("T" + typeRandomNumber.ToString()));
// create a dynamic assembly
AssemblyName assemblyName = new AssemblyName();
assemblyName.Name = "TA" + typeRandomNumber.ToString();
AssemblyBuilder assemblyBuilder = Thread.GetDomain().DefineDynamicAssembly(assemblyName, AssemblyBuilderAccess.Run);
// Create a module
ModuleBuilder module = assemblyBuilder.DefineDynamicModule(string.Format("T{0}Mod", typeRandomNumber));
// create a new type builder (with or without use of a base type)
TypeBuilder typeBuilder = module.DefineType(
string.Format("T{0}", typeRandomNumber),
TypeAttributes.Public | TypeAttributes.Class, typeof(TableEntity));
var properties = AnonymousObject.GetType().GetProperties().Where(
c => c.DeclaringType == AnonymousObject.GetType());
// Loop over the fields that will be used as the properties in our new type
foreach (var f in properties)
{
Type propertyType = f.PropertyType;
string propertyName = f.Name;
// Generate the field that will be manipulated with the property's
// get and set methods
FieldBuilder field = typeBuilder.DefineField(
"_" + propertyName, propertyType, FieldAttributes.Private);
// Generate the public property
PropertyBuilder property = typeBuilder.DefineProperty(
propertyName, System.Reflection.PropertyAttributes.None,
propertyType, new Type[] { propertyType });
// Define the attributes for the getter and setter of the property
MethodAttributes propertyAttributes =
MethodAttributes.Public | MethodAttributes.HideBySig;
// Declare the accessor (get) method for the field we made previously.
MethodBuilder getMethod = typeBuilder.DefineMethod(
"get_value", propertyAttributes, propertyType, Type.EmptyTypes);
// Write a method in IL to read our field and return it
ILGenerator accessorILGenerator = getMethod.GetILGenerator();
accessorILGenerator.Emit(OpCodes.Ldarg_0);
accessorILGenerator.Emit(OpCodes.Ldfld, field);
accessorILGenerator.Emit(OpCodes.Ret);
// Declare the mutator (set) method for the field we made previously.
MethodBuilder setMethod = typeBuilder.DefineMethod(
"set_value", propertyAttributes, null, new Type[] { propertyType });
// Write a method in IL to update our field with the new value
ILGenerator mutatorILGenerator = setMethod.GetILGenerator();
mutatorILGenerator.Emit(OpCodes.Ldarg_0);
mutatorILGenerator.Emit(OpCodes.Ldarg_1);
mutatorILGenerator.Emit(OpCodes.Stfld, field);
mutatorILGenerator.Emit(OpCodes.Ret);
// Now we tie our fancy IL to the actual property in our assembly,
// and the deed is done!
property.SetGetMethod(getMethod);
property.SetSetMethod(setMethod);
}
// Create and store the type for future use (while memory lasts)
Type resultingType = typeBuilder.CreateType();
EntityTypeDictionary.Add(string.Format("T{0}", typeRandomNumber), resultingType);
// And finally, return our brand new custom type
return resultingType;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment