如何获取局部变量的表达式
How to get expression for a local variable
我正在制作一个支持插件的框架,因此它会在应用程序启动时加载插件 dll 中定义的 类。
foreach (Type t in assembly.GetTypes()) {
if (t.IsAssignableTo(typeof(AIGameBodyBehaviour))) {
AIGameBodyBehaviourFactory factory = new AIGameBodyBehaviourFactory() {
Id = t.Name,
NewAIGameBodyBehaviour = Expression.Lambda<Func<AIGameBodyBehaviourFactoryArguments, AIGameBodyBehaviour>>(
Expression.New(
t.GetConstructor(new Type[] {typeof(AIGameBodyBehaviourFactoryArguments) }),
new Expression[] {
//stuck at here
}
),
new ParameterExpression[] {
Expression.Parameter(typeof(AIGameBodyBehaviourFactoryArguments), "arguments")
}
).Compile()
};
EntityLoaderInterface.AddAIGameBodyBehaviourFactory(factory);
}
}
如上所示,complied lambda 采用 AIGameBodyBehaviourFactoryArguments 类型的参数和 return AIGameBodyBehaviour 的实例。 lambda函数体是对用户定义的AIGameBodyBehaviour子类的构造函数的调用。
lambda表达式的参数名为“arguments”。这个名称应该被重新用作表示要传递给构造函数的值的表达式。但是,即使在检查了 the documentation provided by Microsoft 并通过 Google 进行了一些研究之后,我仍然找不到如何执行此操作。
当你被表达式卡住的时候,可以考虑SharpLab。如果我理解正确的话,你想要一个看起来像这样的表达式:
Expression<Func<AIGameBodyBehaviourFactoryArguments, AIGameBodyBehaviour>> expression =
(arguments) => new AIGameBodyBehaviour(arguments);
SharpLab 会告诉你编译器会将这一行变成
ParameterExpression parameterExpression = Expression.Parameter(typeof(AIGameBodyBehaviourFactoryArguments), "arguments");
ConstructorInfo constructor = (ConstructorInfo)MethodBase.GetMethodFromHandle((RuntimeMethodHandle)/*OpCode not supported: LdMemberToken*/);
Expression[] array = new Expression[1];
array[0] = parameterExpression;
NewExpression body = Expression.New(constructor, (IEnumerable<Expression>)array);
ParameterExpression[] array2 = new ParameterExpression[1];
array2[0] = parameterExpression;
Expression<Func<AIGameBodyBehaviourFactoryArguments, AIGameBodyBehaviour>> expression = Expression.Lambda<Func<AIGameBodyBehaviourFactoryArguments, AIGameBodyBehaviour>>(body, array2);
您可以看到 ParameterExpression
的相同实例用作 Expression.New
中的第二个参数和 Expression.Lambda
中的第二个参数。因此,您的代码应如下所示:
foreach (Type t in assembly.GetTypes()) {
if (t.IsAssignableTo(typeof(AIGameBodyBehaviour))) {
var parameterExpression = Expression.Parameter(typeof(AIGameBodyBehaviourFactoryArguments), "arguments");
AIGameBodyBehaviourFactory factory = new AIGameBodyBehaviourFactory() {
Id = t.Name,
NewAIGameBodyBehaviour = Expression.Lambda<Func<AIGameBodyBehaviourFactoryArguments, AIGameBodyBehaviour>>(
Expression.New(
t.GetConstructor(new Type[] {typeof(AIGameBodyBehaviourFactoryArguments) }),
new Expression[] {
parameterExpression
}
),
new ParameterExpression[] {
parameterExpression
}
).Compile()
};
EntityLoaderInterface.AddAIGameBodyBehaviourFactory(factory);
}
}
我正在制作一个支持插件的框架,因此它会在应用程序启动时加载插件 dll 中定义的 类。
foreach (Type t in assembly.GetTypes()) {
if (t.IsAssignableTo(typeof(AIGameBodyBehaviour))) {
AIGameBodyBehaviourFactory factory = new AIGameBodyBehaviourFactory() {
Id = t.Name,
NewAIGameBodyBehaviour = Expression.Lambda<Func<AIGameBodyBehaviourFactoryArguments, AIGameBodyBehaviour>>(
Expression.New(
t.GetConstructor(new Type[] {typeof(AIGameBodyBehaviourFactoryArguments) }),
new Expression[] {
//stuck at here
}
),
new ParameterExpression[] {
Expression.Parameter(typeof(AIGameBodyBehaviourFactoryArguments), "arguments")
}
).Compile()
};
EntityLoaderInterface.AddAIGameBodyBehaviourFactory(factory);
}
}
如上所示,complied lambda 采用 AIGameBodyBehaviourFactoryArguments 类型的参数和 return AIGameBodyBehaviour 的实例。 lambda函数体是对用户定义的AIGameBodyBehaviour子类的构造函数的调用。
lambda表达式的参数名为“arguments”。这个名称应该被重新用作表示要传递给构造函数的值的表达式。但是,即使在检查了 the documentation provided by Microsoft 并通过 Google 进行了一些研究之后,我仍然找不到如何执行此操作。
当你被表达式卡住的时候,可以考虑SharpLab。如果我理解正确的话,你想要一个看起来像这样的表达式:
Expression<Func<AIGameBodyBehaviourFactoryArguments, AIGameBodyBehaviour>> expression =
(arguments) => new AIGameBodyBehaviour(arguments);
SharpLab 会告诉你编译器会将这一行变成
ParameterExpression parameterExpression = Expression.Parameter(typeof(AIGameBodyBehaviourFactoryArguments), "arguments");
ConstructorInfo constructor = (ConstructorInfo)MethodBase.GetMethodFromHandle((RuntimeMethodHandle)/*OpCode not supported: LdMemberToken*/);
Expression[] array = new Expression[1];
array[0] = parameterExpression;
NewExpression body = Expression.New(constructor, (IEnumerable<Expression>)array);
ParameterExpression[] array2 = new ParameterExpression[1];
array2[0] = parameterExpression;
Expression<Func<AIGameBodyBehaviourFactoryArguments, AIGameBodyBehaviour>> expression = Expression.Lambda<Func<AIGameBodyBehaviourFactoryArguments, AIGameBodyBehaviour>>(body, array2);
您可以看到 ParameterExpression
的相同实例用作 Expression.New
中的第二个参数和 Expression.Lambda
中的第二个参数。因此,您的代码应如下所示:
foreach (Type t in assembly.GetTypes()) {
if (t.IsAssignableTo(typeof(AIGameBodyBehaviour))) {
var parameterExpression = Expression.Parameter(typeof(AIGameBodyBehaviourFactoryArguments), "arguments");
AIGameBodyBehaviourFactory factory = new AIGameBodyBehaviourFactory() {
Id = t.Name,
NewAIGameBodyBehaviour = Expression.Lambda<Func<AIGameBodyBehaviourFactoryArguments, AIGameBodyBehaviour>>(
Expression.New(
t.GetConstructor(new Type[] {typeof(AIGameBodyBehaviourFactoryArguments) }),
new Expression[] {
parameterExpression
}
),
new ParameterExpression[] {
parameterExpression
}
).Compile()
};
EntityLoaderInterface.AddAIGameBodyBehaviourFactory(factory);
}
}