1、參考: http://blog.zhaojie.me/2010/05/generate-dynamic-method-with-expression-tree-in-dot-net-4.html
2、主要類
public static class AnonymousFactory
{
//private static ConcurrentDictionary<Type, Type> s_dynamicTypes = new ConcurrentDictionary<Type, Type>();
//private static Func<dynamic, Type> s_dynamicTypeCreator = new Func<dynamic, Type>(CreateAnonymousType);
//private static ConcurrentDictionary<Type, Func<object, object>> s_dynamicEntityFactories =
//new ConcurrentDictionary<Type, Func<object, object>>();
//private static Func<dynamic, Func<object, object>> s_factoryCreator = new Func<dynamic, Func<object, object>>(DynamicFactoryCreator);
public static object ToAnonymousRef(dynamic entity)
{
var entityType = entity.GetType();
//var dynamicType = s_dynamicTypes.GetOrAdd(entityType, s_dynamicTypeCreator(entity));
var dynamicType = CreateAnonymousType(entity);
var dynamicObject = Activator.CreateInstance(dynamicType);
var dict = (IDictionary<string, object>)entity;
foreach (var key in dict.Keys)
{
var value = dict[key];
dynamicType.GetField(key).SetValue(dynamicObject, value);
}
return dynamicObject;
}
public static object ToAnonymous(dynamic entity)
{
var entityType = entity.GetType();
//var factory = s_dynamicEntityFactories.GetOrAdd(entityType, s_factoryCreator(entity));
var factory = DynamicFactoryCreator(entity);
return factory(entity);
}
public static object ToAnonymousNoParam(dynamic entity)
{
var entityType = entity.GetType();
//var factory = s_dynamicEntityFactories.GetOrAdd(entityType, s_factoryCreator(entity));
var factory = DynamicFactoryCreatorNoParam(entity);
return factory();
}
private static Type CreateAnonymousType(dynamic entity)
{
var guid = Guid.NewGuid();
string strDynamicModuleName = "Anonymous_" + guid;
string strDynamicClassName = "<>Anonymous_" + guid;
AppDomain currentDomain = System.AppDomain.CurrentDomain;
AssemblyName assemblyName = new AssemblyName(strDynamicModuleName);
AssemblyBuilder assemblyBuilder = currentDomain.DefineDynamicAssembly(assemblyName, AssemblyBuilderAccess.Run);
ModuleBuilder moduleBuilder = assemblyBuilder.DefineDynamicModule(strDynamicModuleName);
TypeBuilder typeBuilder = moduleBuilder.DefineType(strDynamicClassName, TypeAttributes.Public);
var dict = (IDictionary<string, object>)entity;
foreach (var key in dict.Keys)
{
typeBuilder.DefineField(key, dict[key].GetType(), FieldAttributes.Public);
}
return typeBuilder.CreateType();
}
public static void TestInsert()
{
Func<int, List<int>> t6 = t => { return new List<int> { t, 2 }; };
// define the parameter
var parameterExpr = Expression.Parameter(typeof(int), "t");
// collect the body
var bodyExprs = new List<Expression>();
var anonymousType = typeof(List<int>);
// code: var AnonymousEntity = new DynamicType();
var anonymousEntityExpr = Expression.Variable(anonymousType, "AnonymousEntity");
var newAnonymousTypeExpr = Expression.New(anonymousType);
var assignDynamicEntityExpr = Expression.Assign(anonymousEntityExpr, newAnonymousTypeExpr);
bodyExprs.Add(assignDynamicEntityExpr);
MethodInfo addMethod = anonymousType.GetMethod("Add");
bodyExprs.Add(Expression.Call(anonymousEntityExpr, addMethod, parameterExpr));
bodyExprs.Add(Expression.Call(anonymousEntityExpr, addMethod, Expression.Constant(2)));
// code: return (object)dynamicEntity;
var castResultExpr = Expression.Convert(anonymousEntityExpr, typeof(List<int>));
bodyExprs.Add(castResultExpr);
var methodBodyExpr = Expression.Block(
typeof(List<int>), /* return type */
new[] { anonymousEntityExpr }, /* local variables */
bodyExprs /* body expressions */);
// code: entity => { ... }
var lambdaExpr = Expression.Lambda<Func<int, List<int>>>(methodBodyExpr, parameterExpr);
var testFun = lambdaExpr.Compile();
var result = testFun(5);
}
private static Func<object, object> DynamicFactoryCreator(dynamic entity)
{
dynamic expando = new System.Dynamic.ExpandoObject(); //動態類型字段 可讀可寫
expando.Id = 1;
expando.Name = "Test";
var t2 = new { expando.Id, expando.Name };
Func<object, object> buildEntity = t =>
{
return new
{
expando.Id,
expando.Name
};
};
var anonymousType = CreateAnonymousType(entity);
// define the parameter
var parameterExpr = Expression.Parameter(typeof(object), "entity");
// collect the body
var bodyExprs = new List<Expression>();
// code: var AnonymousEntity = new DynamicType();
var anonymousEntityExpr = Expression.Variable(anonymousType, "AnonymousEntity");
var newAnonymousTypeExpr = Expression.New(anonymousType);
var assignDynamicEntityExpr = Expression.Assign(anonymousEntityExpr, newAnonymousTypeExpr);
bodyExprs.Add(assignDynamicEntityExpr);
// generate code for fields' assignments
var dict = (IDictionary<string, object>)entity;
foreach (var key in dict.Keys)
{
var fieldExpr = Expression.Field(anonymousEntityExpr, key);
var constExpr = Expression.Constant(dict[key]);
var assignFieldExpr = Expression.Assign(fieldExpr, constExpr);
bodyExprs.Add(assignFieldExpr);
}
// code: return (object)dynamicEntity;
var castResultExpr = Expression.Convert(anonymousEntityExpr, typeof(object));
bodyExprs.Add(castResultExpr);
// code: { ... }
var methodBodyExpr = Expression.Block(
typeof(object), /* return type */
new ParameterExpression[] { anonymousEntityExpr }, /* local variables */
bodyExprs /* body expressions */);
// code: entity => { ... }
var lambdaExpr = Expression.Lambda<Func<object, object>>(methodBodyExpr, parameterExpr);
return lambdaExpr.Compile();
}
private static Func<object> DynamicFactoryCreatorNoParam(dynamic entity)
{
dynamic expando = new System.Dynamic.ExpandoObject(); //動態類型字段 可讀可寫
expando.Id = 1;
expando.Name = "Test";
var t2 = new { expando.Id, expando.Name };
Func<object> buildEntity = () =>
{
return new
{
expando.Id,
expando.Name
};
};
var anonymousType = CreateAnonymousType(entity);
// define the parameter
var parameterExpr = Expression.Parameter(typeof(object), "entity");
// collect the body
var bodyExprs = new List<Expression>();
// code: var AnonymousEntity = new DynamicType();
var anonymousEntityExpr = Expression.Variable(anonymousType, "AnonymousEntity");
var newAnonymousTypeExpr = Expression.New(anonymousType);
var assignDynamicEntityExpr = Expression.Assign(anonymousEntityExpr, newAnonymousTypeExpr);
bodyExprs.Add(assignDynamicEntityExpr);
// generate code for fields' assignments
var dict = (IDictionary<string, object>)entity;
foreach (var key in dict.Keys)
{
var fieldExpr = Expression.Field(anonymousEntityExpr, key);
var constExpr = Expression.Constant(dict[key]);
var assignFieldExpr = Expression.Assign(fieldExpr, constExpr);
bodyExprs.Add(assignFieldExpr);
}
// code: return (object)dynamicEntity;
var castResultExpr = Expression.Convert(anonymousEntityExpr, typeof(object));
bodyExprs.Add(castResultExpr);
// code: { ... }
var methodBodyExpr = Expression.Block(
typeof(object), /* return type */
new ParameterExpression[] { anonymousEntityExpr }, /* local variables */
bodyExprs /* body expressions */);
// code: entity => { ... }
var lambdaExpr = Expression.Lambda<Func<object>>(methodBodyExpr);
return lambdaExpr.Compile();
}
}
3、調用
static void Main(string[] args)
{
dynamic expando = new System.Dynamic.ExpandoObject(); //動態類型字段 可讀可寫
expando.Id = 1;
expando.Name = "Test";
var t2 = new { expando.Id, expando.Name };
var t3 = AnonymousFactory.ToAnonymousRef(expando);
var t4 = AnonymousFactory.ToAnonymous(expando);
var t5 = AnonymousFactory.ToAnonymousNoParam(expando);
AnonymousFactory.TestInsert();
}