-
-
Save regionbbs/25d609730d3d4ab3a1d8 to your computer and use it in GitHub Desktop.
TableOperationUtil class
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
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