Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/309.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

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# 通过LINQ转换和应用表达式?_C#_Linq_.net 4.5 - Fatal编程技术网

C# 通过LINQ转换和应用表达式?

C# 通过LINQ转换和应用表达式?,c#,linq,.net-4.5,C#,Linq,.net 4.5,我希望支持表达式passthru,如下所示: public IFastIndexingCollection<T> { // Main data structure here = // Key = property name // Value = class below private Dictionary<string, ICustomCollection<T, U>> _indexedItems; public IEnume

我希望支持表达式passthru,如下所示:

public IFastIndexingCollection<T> {
   // Main data structure here = 
   // Key = property name
   // Value = class below
   private Dictionary<string, ICustomCollection<T, U>> _indexedItems;

   public IEnumerable<T> FindWhere(Expression<Func<T, bool>> expression);
}

internal ICustomCollection<T, U> {
     // Main data structure =
     // T = type of data structure, e.g., Phone
     // U = property type, e.g., string
     // Key = value for given property (e.g., "Samsung")
     // Value = List<T> of items matching that key
     private ILookup<U, T> _backingLookup;
}
我只是不知道如何在if中指定的位置应用LINQ表达式。想法?

使用名为Replace的公共表达式visitor,您可以在获得获取属性或字段名所需的MemberExpression后转换测试

public static ExpressionExt {
    /// <summary>
    /// Replaces an Expression (reference Equals) with another Expression
    /// </summary>
    /// <param name="orig">The original Expression.</param>
    /// <param name="from">The from Expression.</param>
    /// <param name="to">The to Expression.</param>
    /// <returns>Expression with all occurrences of from replaced with to</returns>
    public static Expression Replace(this Expression orig, Expression from, Expression to) => new ReplaceVisitor(from, to).Visit(orig);
}

/// <summary>
/// ExpressionVisitor to replace an Expression (that is Equals) with another Expression.
/// </summary>
public class ReplaceVisitor : ExpressionVisitor {
    readonly Expression from;
    readonly Expression to;

    public ReplaceVisitor(Expression from, Expression to) {
        this.from = from;
        this.to = to;
    }

    public override Expression Visit(Expression node) => node == from ? to : base.Visit(node);
}
您可以使用将成员访问权从测试中分离出来的FindWhere版本来提高性能:

public override IEnumerable<T> FindWhere2<U>(Expression<Func<T, U>> accessExpr, Func<U, bool> testFn);

var ans = fic.FindWhere2(x => x.Manufacturer, y => y.IndexOf("Samsung") > -1);

什么是查找?它不会出现在示例类中。。。在代码中简化/替换总是一个坏主意,因为您经常出错。我不清楚你的第二点。还有最低级别对3的含义。当一个字典每个键只能有一个值(我假设是属性名)时,为什么第1点说valuess?_indexedItems上的注释,表示类似//Key=property name;值=Lookup@NetMage-为了清晰起见,我进行了编辑。基本问题是,我需要以某种方式转换传入表达式,以删除那些封装在_backingLookup中的属性。所以x.制造商指数。。。实际上只是x.IndexOf。。。因为查找已锁定到制造商属性的所有可能值Y您的代码不可编译U在IFastIndexingCollection中未定义,没有接口关键字,接口中不允许字段,这使得回答您的问题变得困难。什么是FastIndexingCollection?谢谢!这足够让我走了。ExpressionVisitor w/Replace扩展就是我所需要的。
public static ExpressionExt {
    /// <summary>
    /// Replaces an Expression (reference Equals) with another Expression
    /// </summary>
    /// <param name="orig">The original Expression.</param>
    /// <param name="from">The from Expression.</param>
    /// <param name="to">The to Expression.</param>
    /// <returns>Expression with all occurrences of from replaced with to</returns>
    public static Expression Replace(this Expression orig, Expression from, Expression to) => new ReplaceVisitor(from, to).Visit(orig);
}

/// <summary>
/// ExpressionVisitor to replace an Expression (that is Equals) with another Expression.
/// </summary>
public class ReplaceVisitor : ExpressionVisitor {
    readonly Expression from;
    readonly Expression to;

    public ReplaceVisitor(Expression from, Expression to) {
        this.from = from;
        this.to = to;
    }

    public override Expression Visit(Expression node) => node == from ? to : base.Visit(node);
}
public override IEnumerable<T> FindWhere(Expression<Func<T, bool>> testFn) {
    var testBody = (BinaryExpression)testFn.Body;
    var fldTestExpr = testBody.Left;
    if (fldTestExpr.NodeType == ExpressionType.Call)
        fldTestExpr = ((MethodCallExpression)fldTestExpr).Object;

    if (fldTestExpr is MemberExpression me) {
        var memberName = me.Member.Name;

        var newp = Expression.Parameter(me.Type);
        var newBody = testBody.Replace(me, newp);
        var newLambda = Expression.Lambda(newBody, newp);

        var newTestFn = newLambda.Compile();
        var testans = (bool) newTestFn.DynamicInvoke("this Samsung that");
        // using DynamicInvoke is not terrible efficient, but lacking a static
        // type for the property means the compiler must use object
    }
}
public override IEnumerable<T> FindWhere2<U>(Expression<Func<T, U>> accessExpr, Func<U, bool> testFn);

var ans = fic.FindWhere2(x => x.Manufacturer, y => y.IndexOf("Samsung") > -1);