C# 通过LINQ转换和应用表达式?
我希望支持表达式passthru,如下所示: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
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);