在运行时使用新的匿名类型创建lambda表达式

我想调用一个需要这样的参数的方法:

Expression<Func> expr 

我需要在运行时构造这个参数,因为我不知道匿名类型之前会是什么样子; 它可以有任何数量的字段:

 x => new { a=xa, b=xb, c=xc, etc... } 

我可以在运行时创建一个具有相同“签名”的类型(这是正确的词吗?)作为所需的匿名类型,但问题是:如何在运行时从那个构造这个lambda表达式? 特别是Expression.New让我烦恼,因为我需要传递一个构造函数信息,我必须从现有类型传递它(它确实可以是一个匿名类型,但我不能在运行时创建一个匿名类型。或者是否存在一种方法吗?)。

更新 (评论中要求的某些上下文)

我想调用的方法是:

 DependentNavigationPropertyConfiguration.HasForeignKey(Expression<Func> foreignKeyExpression) 

我想这样做的原因是自动为从某个基类inheritance的实体创建一个导航属性,包括该外键中该基类的键。 因为实体可以有多个任何类型的键字段,所以TKey类型只在运行时才为我所知。

使用单独的方法:

 public static void Main() { var myExpression = Express(str => new { String = str, Length = str.Length }); // We can compile/use it as well... var compiledExpression = myExpression.Compile(); var anonymousOutput = compiledExpression("Input String"); Console.WriteLine(anonymousOutput.String); // Output: Input String Console.WriteLine(anonymousOutput.Length); // Output: 12 Debug.WriteLine(myExpression); // Output: "str => new <>f__AnonymousType0`2(String = str, Length = str.Length)" Console.ReadLine(); } static Expression> Express(Expression> expression) { return expression; } 

但请注意,必须事先知道起始类型(在我的示例中为String )。

更新

既然你想要做的就是动态创建一个类型,我会给你一个如何做到这一点的简单例子。

 public static void Main() { // Create an anonymous type with two fields Type myAnonymousType = CreateNewType(); dynamic myAnon = Activator.CreateInstance(myAnonymousType); myAnon.FieldA = "A String"; myAnon.FieldB = 1234; Console.WriteLine(myAnon.FieldA); // Output : "AString" Console.WriteLine(myAnon.FieldB); // Output : 1234 Console.ReadLine(); } public static Type CreateNewType() { // Let's start by creating a new assembly AssemblyName dynamicAssemblyName = new AssemblyName("MyAsm"); AssemblyBuilder dynamicAssembly = AssemblyBuilder.DefineDynamicAssembly(dynamicAssemblyName, AssemblyBuilderAccess.Run); ModuleBuilder dynamicModule = dynamicAssembly.DefineDynamicModule("MyAsm"); // Now let's build a new type TypeBuilder dynamicAnonymousType = dynamicModule.DefineType("MyAnon", TypeAttributes.Public); // Let's add some fields to the type. FieldInfo dynamicFieldA = dynamicAnonymousType.DefineField("FieldA", typeof(TFieldTypeA), FieldAttributes.Public); FieldInfo dynamicFieldB = dynamicAnonymousType.DefineField("FieldB", typeof(TFieldTypeB), FieldAttributes.Public); // Return the type to the caller return dynamicAnonymousType.CreateType(); } 

如您所见,这有点复杂。 如果你想进一步研究这个话题,请务必参考Reflectoin.Emit

匿名类型是编译器function。 如果你没有让编译器在编译时创建它们,那么你将不得不使用元编程 – TypeBuilderCSharpCodeProvider 。 你可能最好使用元组 – 至少它们很容易创建(你可以很容易地使用Tuple.Create )。

至于表达; 我建议输入它作为Expression> – 这适用于任何配方。 检查 Expression的代码当然可以看到实际类型是什么。

你可以这样做

 context.Students.Join(context.Courses, a => a.Course_id, b => b.Course_id, (a, b) => new { Student= a, Course= b }).Where(x => x.Student_id == studentId) .Select(y => new { StudentId = y.Student.StudentId, RegistrationNumber = y.Student.RegNo, Name = y.Student.Name, Coursename = y.Course.Name }).ToList();