net Lamada表达式构建匿名对象

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();
}

完整的代码https://download.csdn.net/download/xinshun/11962000

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值