使用反射创建表达式我使用Moq创建了一个数据集的模拟。我创建了一个小助手类,它允许我有一个内存存储而不是数据库,使单元测试变得轻而易举。这样我就可以在我的模拟数据集中添加和删除项目,这让我可以测试我的插入和删除服务调用。在模拟的设置过程中,我有这样一行。Setup(i=>i.AcademicCycles).Returns(mockStore.GetList());我的mock有很多属性,所以我想使用反射来执行这个设置步骤。我已经设法让Returns部分通过反射工作,但我仍然坚持使用lambda方法进行设置。安装程序需要一个Expression>对应于i=>i.AcademicCycles并且我想动态创建它。使用反射我有以下内容:属性名称:“AcademicCycles”类型IQueryable类型AcademicCycle我在lambda语句中还有一个i实例,它是一个GoalsModelUnitOfWork动态创建表达式的代码如下:ParameterExpressionparameter=Expression.Parameter(typeof(GoalsModelUnitOfWork),"i");MemberExpressionproperty=Expression.Property(parameter,"AcademicCycles");varqueryableType=typeof(IQueryable).MakeGenericType(typeof(AcademicCycle));vardelegateType=typeof(Func).MakeGenericType(typeof(GoalsModelUnitOfWork),queryableType);varyourExpression=Expression.Lambda(delegateType,property,parameter);结果将具有所需的类型,但问题是Expression.Lambda()的返回类型是LambdaExpression并且您不能对Expression>执行类型转换以将其作为参数传递给设置函数,因为您不知道Func的泛型类型参数。所以你必须通过反射调用Setup方法:this.GetType().GetMethod("Setup",yourExpression.GetType()).Invoke(this,yourExpression);我决定给它一个hack并最终得到这个可怕的代码。我不是反射专家,这只是让事情发挥作用的第一次尝试。我会对人们采用的其他方法感兴趣,或者是否有任何反射包装器库可以使它变得更好。使用系统;使用System.Collections.Generic;使用System.Linq;使用System.Linq.Expressions;使用System.Reflection;使用最小起订量;使用Xunit;namespaceMyExample{publicclassTests{[Fact]publicvoidTest(){Dictionarydata=newDictionary{{typeof(IQueryable),newList{newCycle{Name="Test"}}.AsQueryable()},{typeof(IQueryable),newList{newRider{Name="1"},newRider{Name="2"}}.AsQueryable()}};varmock=newMock();varsetup=mock.GetType().GetMethods().Single(d=>d.Name=="Setup"&&d.ContainsGenericParameters);varparam=Expression.Parameter(typeof(IDataContext),"i");foreach(varpropertyintypeof(IDataContext).GetProperties(BindingFlags.Public|BindingFlags.Instance)){//构建lambdavarex=Expression.Lambda(Expression.MakeMemberAccess(param,property),param);//获取Setup方法的通用版本vartypedSetup=setup.MakeGenericMethod(property.PropertyType);//运行安装程序方法varreturnedSetup=typedSetup.Invoke(mock,new[]{ex});//获取IReturns接口的通用版本variReturns=typedSetup.ReturnType.GetInterfaces().Single(d=>d.Name.StartsWith("IReturns`"));//获取通用Returns方法varreturns=iReturns.GetMethod("Returns",newType[]{property.PropertyType});//运行传入数据的returns方法returns.Invoke(returnedSetup,new[]{data[property.PropertyType]});}Assert.Equal(1,mock.Object.Cycles.Count());}}publicclassCycle{publicstringName{get;放;}}publicclassRider{publicstringName{get;放;}}publicinterfaceIDataContext{IQueryableCycles{get;放;}IQueryableRiders{get;放;}}}该方法应该构造lambda表达式由于您是通过反射调用Setup方法,因此不需要强类型的lambda表达式;调用Invoke时将其作为对象数组的一部分传递:varmemberExpression=Expression.Property(参数,propertyName);varlambdaExpression=Expression.Lambda(memberExpression,参数);返回lambda表达式;我不认为你真的需要参数名称。如果我是对的,你可以简化一下:以上就是C#学习教程:使用反射创建表达式的全部内容。如果对大家有用,需要进一步了解C#学习教程,希望大家多多关注—publicLambdaExpressionPropertyGetLambda(TypeparameterType,stringpropertyName,TypepropertyType){varmemberExpression=Expression.Property(参数,propertyName);varlambdaExpression=Expression.Lambda(memberExpression,参数);返回lambda表达式;}本文收集自网络,不代表立场。如涉及侵权,请点击右侧联系管理员删除。如需转载请注明出处: