我想调用一个方法,它需要一个像这样的参数:
Expression<Func<sometype, 'a>> expr
我需要在运行时构造这个参数,因为我不知道匿名类型之前是什么样子的;它可以有任意数量的字段:
x => new { a=x.a, b=x.b, c=x.c, etc... }
我可以在运行时创建一个类型,具有相同的"签名"(这是正确的词吗?)作为所需的匿名类型,但问题是:我如何在运行时构造这个lambda表达式?尤其是表达式。New让我很困扰,因为我需要传递一个constructorInfo给它,我必须从一个现有的类型(它确实可以是一个匿名类型,但我不能在运行时创建一个匿名类型)中获得。或者有办法做到吗?)。
更新(注释中要求的一些上下文)
我想调用的方法是:
DependentNavigationPropertyConfiguration.HasForeignKey<TKey>(Expression<Func<TDependentEntityType, TKey>> foreignKeyExpression)
我想这样做的原因是自动使从某个基类继承的实体的导航属性在外键中包含该基类的键。因为一个实体可以有多个任意类型的键字段,所以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<Func<String, T>> Express<T>(Expression<Func<String, T>> expression)
{
return expression;
}
但是请注意,必须预先知道起始类型(在我的示例中是String
)。
:
因为听起来你要做的是动态创建一个类型,我给你一个简单的例子来说明如何做到这一点。
public static void Main()
{
// Create an anonymous type with two fields
Type myAnonymousType = CreateNewType<String, Int32>();
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<TFieldTypeA, TFieldTypeB>()
{
// 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();
}
如您所见,这有点复杂。如果你想进一步研究这个话题,一定要参考Reflection.Emit
。
匿名类型是编译器的一个特性。如果您没有让编译器在编译时创建它们,那么您将不得不使用元编程—TypeBuilder
或CSharpCodeProvider
。你最好使用元组——至少它们很容易创建(你可以很容易地使用Tuple.Create
)。
对于表达式;我建议将其输入为Expression<Func<sometype, object>>
-这将适用于任何配方。代码检查 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();