Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/linq/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C#在运行时使用字符串创建表达式_C#_Linq_Runtime_Expression - Fatal编程技术网

C#在运行时使用字符串创建表达式

C#在运行时使用字符串创建表达式,c#,linq,runtime,expression,C#,Linq,Runtime,Expression,那么让我们假设我有以下方式的方法: public T Get<T, U>(Expression<Func<T, U>> expr) { // use the expression to retrieve cool stuff. } 然后有另一个类栏: public class Bar { public string AnotherName { get; set; } } 现在我想编译一个如下所示的表达式: Foo foo = new Foo

那么让我们假设我有以下方式的方法:

public T Get<T, U>(Expression<Func<T, U>> expr) {
    // use the expression to retrieve cool stuff.
}
然后有另一个类栏:

public class Bar {
    public string AnotherName { get; set; }
}
现在我想编译一个如下所示的表达式:

Foo foo = new Foo { Name = "AName" };
Expression<Func<Bar, string>> expr = p => p.AnotherName == foo.Name;
例如:

var sourceValue = "AName";
var targetClassName = "Bar";
var targetPropertyName = "AnotherName";

var expr = string.Format("{0}.{1} == {2}", 
    targetClassName, targetPropertyName, sourceValue);

var p = Expression.Parameter(typeof(Bar), "Target");
var e = System.Linq.Dynamic.DynamicExpression.ParseLambda(new[] { p }, null, expr);
var lambda = e.Compile();
但是,这只会导致对lambda表达式的委托


我现在的问题是,是否可以通过在运行时创建这样的表达式来调用Get方法?

我认为您不需要动态:

var sourceValue = "AName";

// You will need the namespace of Bar here!
var namespaceTargetClassName = "ExpressionProblem";
var targetClassName = "Bar";
var targetPropertyName = "AnotherName";

{
    var targetType = Type.GetType(namespaceTargetClassName + "." + targetClassName);
    var p = Expression.Parameter(targetType, "Target");
    var pr = Expression.PropertyOrField(p, targetPropertyName);
    var e = Expression.Equal(pr, Expression.Constant(sourceValue));
    var lambda = Expression.Lambda(e, p); // It would be an Expression<Func<Bar, bool>>
}
var sourceValue=“AName”;
//您需要在这里使用Bar的名称空间!
var namespaceTargetClassName=“ExpressionProblem”;
var targetClassName=“Bar”;
var targetPropertyName=“其他名称”;
{
var targetType=Type.GetType(namespaceTargetClassName+“+”+targetClassName);
var p=表达式参数(targetType,“Target”);
var pr=Expression.PropertyOrField(p,targetPropertyName);
var e=表达式.Equal(pr,表达式.Constant(sourceValue));
var lambda=Expression.lambda(e,p);//它将是一个表达式
}
请注意,第一种解决方案有一个问题:您生成的委托类型是
Func
,因此您无法轻松编译和使用它

创建内部执行强制转换的
Func
更容易

{
    var targetType = Type.GetType(namespaceTargetClassName + "." + targetClassName);
    var p = Expression.Parameter(typeof(object), "Target");

    // I'm using the as operator here, if you prefer a "strong" 
    // cast (the cast operator that throws if the object is of
    // invalid type), use Expression.Convert with the same syntax 
    var pcasted = Expression.TypeAs(p, targetType); 
    var pr = Expression.PropertyOrField(pcasted, targetPropertyName);
    var e = Expression.Equal(pr, Expression.Constant(sourceValue));
    var lambda = Expression.Lambda<Func<object, bool>>(e, p);

    Func<object, bool> func = lambda.Compile();

    Bar obj = new Bar { AnotherName = "AName" };
    bool res = func(obj);
}
{
var targetType=Type.GetType(namespaceTargetClassName+“+”+targetClassName);
var p=表达式参数(typeof(object),“Target”);
//我在这里使用as运算符,如果你喜欢“强”
//cast(如果对象是
//无效类型),请使用表达式。使用相同语法进行转换
var pcasted=Expression.TypeAs(p,targetType);
var pr=Expression.PropertyOrField(pcasted,targetPropertyName);
var e=表达式.Equal(pr,表达式.Constant(sourceValue));
var lambda=表达式lambda(e,p);
Func Func=lambda.Compile();
Bar obj=新的Bar{AnotherName=“AName”};
bool res=func(obj);
}

搜索
CSharpCodeProvider
。也许杀伤力过大,但它会解决你的问题。
var sourceValue = "AName";

// You will need the namespace of Bar here!
var namespaceTargetClassName = "ExpressionProblem";
var targetClassName = "Bar";
var targetPropertyName = "AnotherName";

{
    var targetType = Type.GetType(namespaceTargetClassName + "." + targetClassName);
    var p = Expression.Parameter(targetType, "Target");
    var pr = Expression.PropertyOrField(p, targetPropertyName);
    var e = Expression.Equal(pr, Expression.Constant(sourceValue));
    var lambda = Expression.Lambda(e, p); // It would be an Expression<Func<Bar, bool>>
}
{
    var targetType = Type.GetType(namespaceTargetClassName + "." + targetClassName);
    var p = Expression.Parameter(typeof(object), "Target");

    // I'm using the as operator here, if you prefer a "strong" 
    // cast (the cast operator that throws if the object is of
    // invalid type), use Expression.Convert with the same syntax 
    var pcasted = Expression.TypeAs(p, targetType); 
    var pr = Expression.PropertyOrField(pcasted, targetPropertyName);
    var e = Expression.Equal(pr, Expression.Constant(sourceValue));
    var lambda = Expression.Lambda<Func<object, bool>>(e, p);

    Func<object, bool> func = lambda.Compile();

    Bar obj = new Bar { AnotherName = "AName" };
    bool res = func(obj);
}