1、参考
https://www.jb51.cc/csharp/101154.html
https://www.cnblogs.com/twinhead/p/9160975.html
https://www.cnblogs.com/PurpleTide/archive/2011/02/17/1957062.html
https://www.cnblogs.com/jkswjw/archive/2013/08/13/3252602.html
2、主要代码
private static Type CreateAnonymousType(Dictionary<string, MemberAssignment> dictMember)
{
string tempName = BuildAClassName(dictMember);
string strDynamicModuleName = "md_" + tempName;
string strDynamicClassName = "cls_" + tempName;
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);
// 无参构造函数
typeBuilder.DefineDefaultConstructor(MethodAttributes.Public);
// 有参构造函数
var dict = dictMember.ToDictionary(x => x.Key, x => x.Value.Expression.Type );
Type[] argTypes = dict.Values.ToArray();
var constructorBuilder = typeBuilder.DefineConstructor(MethodAttributes.Public, CallingConventions.Standard, argTypes);
int index = 0;
ILGenerator ilOfCtor = constructorBuilder.GetILGenerator();
foreach (var item in dict.Keys)
{
//类型的属性成员由两部分组成,一是私有字段,二是访问私有字段的属性包装器。
//包装器运行时的本质与 Method 一样,即包含 Set_Method 和 Get_Method 两个方法。
//动态创建字段
FieldBuilder fbBuilder = typeBuilder.DefineField("_" + item, dict[item], FieldAttributes.Private);
index++;
ilOfCtor.Emit(OpCodes.Ldarg_0); //向MSIL流发送属性实例
ilOfCtor.Emit(OpCodes.Ldarg, index); //将指定索引的参数加到堆栈上。
ilOfCtor.Emit(OpCodes.Stfld, fbBuilder); //装载字段
PropertyBuilder propertyBuilder = typeBuilder.DefineProperty(item, PropertyAttributes.None, dict[item], null);
MethodBuilder mGet = typeBuilder.DefineMethod("get_" + item, MethodAttributes.Public, dict[item], null);
ILGenerator ilGet = mGet.GetILGenerator();
ilGet.Emit(OpCodes.Ldarg_0);
ilGet.Emit(OpCodes.Ldfld, fbBuilder); //装载属性私有字段
ilGet.Emit(OpCodes.Ret);
propertyBuilder.SetGetMethod(mGet); // 设置获取属性值的方法
MethodBuilder mSet = typeBuilder.DefineMethod("set_" + item, MethodAttributes.Public, typeof(void), new Type[] { dict[item] });
ILGenerator ilSet = mSet.GetILGenerator();
ilSet.Emit(OpCodes.Ldarg_0);
ilSet.Emit(OpCodes.Ldarg_1);
ilSet.Emit(OpCodes.Stfld, fbBuilder);
ilSet.Emit(OpCodes.Ret);
propertyBuilder.SetSetMethod(mSet); // 设置属性值的方法
}
ilOfCtor.Emit(OpCodes.Ret);
return typeBuilder.CreateType();
}
private static Func<T, object> BuildCreatorByBinding(Dictionary<string, MemberAssignment> dict)
{
var entityType = typeof(T);
var dynamicType = CreateAnonymousType(dict);
// define the parameter
var parameterExpr = Expression.Parameter(typeof(T), "x");
#region 方法二,使用成员绑定
// https://www.jb51.cc/csharp/101154.html
List<MemberAssignment> assignList = new List<MemberAssignment>();
foreach (var key in dict.Keys)
{
var sourceExp = Expression.MakeMemberAccess(parameterExpr, dict[key].Member);
if (dict[key].Expression is ListInitExpression)
{
var listExp = dict[key].Expression as ListInitExpression;
}
var mbs = dynamicType.GetMember(key);
var assignExp = Expression.Bind(mbs.FirstOrDefault(), sourceExp);
assignList.Add(assignExp);
}
var targetNew = Expression.New(dynamicType);
var init = Expression.MemberInit(targetNew, assignList);
code: return (object)dynamicEntity;
var castResultExprTwo = Expression.Convert(init, typeof(object));
var lambda = (Expression<Func<T, object>>)Expression.Lambda(castResultExprTwo, parameterExpr);
#endregion 法二
return lambda.Compile();
}