标签: expression-trees

继承期间的表达推断

我有以下代码:

using System;
using System.Linq;
using System.Linq.Expressions;

public class Program
{
    public static void Main()
    {
        Descendant d = new Descendant();
        d.TestMethod();
    }
}

public class Base
{
    protected void FigureItOut<TClass, TMember>(Expression<Func<TClass, TMember>> expr)
    {

    }
}

public class Descendant : Base
{
    public void TestMethod()
    {
        FigureItOut(c => c.Name);
    }

    public String Name { get; set; }
}
Run Code Online (Sandbox Code Playgroud)

我收到此编译器错误消息:

The type arguments for method
'Base.FigureItOut<TClass,TMember> 
(System.Linq.Expressions.Expression<System.Func<TClass,TMember>>)'
cannot be inferred from the usage. Try specifying the type arguments explicitly.
Run Code Online (Sandbox Code Playgroud)

如果我将对ImageItOut的调用更改为: …

c# type-inference compiler-errors expression-trees

1
推荐指数
1
解决办法
535
查看次数

遍历表达式,找到MethodCallExpression并替换为新的Expression

我有这样的表情 Expression<Func<IInterface, object>>

我如何循环/遍历表达式内的所有表达式并查找使用Func(IInterface)输入参数的任何MethodCallExpression,以调用此类方法

inputParameter => inputParameter.MyMethod(typeof(SomeClass))
Run Code Online (Sandbox Code Playgroud)

或像这样的通用扩展方法

inputParameter => inputParameter.MyMethod<SomeClass>()
Run Code Online (Sandbox Code Playgroud)

如果找到两种方法之一,则需要通过Type。对于通用扩展方法,它将是通用参数,即类型,在另一个方法调用中,它是为方法调用中的参数提供的第一个参数

这两种方法的签名如下所示

object MyMethod(Type type)
T MyMethod<T>(this IInterface param) where T : class
Run Code Online (Sandbox Code Playgroud)

然后,使用两个方法调用之一中的类型查找另一个Expression<Func<IInterface, object>>,并将该方法调用替换为表达式的“内容”。

任何可以帮助我完成此工作的人吗?

搜索表达式以查找对两个方法之一的任何调用(如果找到),获取调用中使用的类型,并查找针对该类型注册的表达式(我在词典中找到它)并将方法调用替换为表达式正在执行的操作。

这是我要完成的示例。如果我有以下两个Expression<Func<IInterface, object>>声明为Bar1和Bar2类型

Bar1: x => new Foo1(x.MyMethod(typeof(Bar2)))
Bar2: x => new Foo2()
Run Code Online (Sandbox Code Playgroud)

解决/合并Func<IInterface, object>Bar1 的for最终看起来像这样

Bar1: x => new Foo1(new Foo2())
Run Code Online (Sandbox Code Playgroud)

x.MyMethod(typeof(Bar2))类型BAR1登记在lambda通话将被替换为new Foo2()类型BAR2免费通话。

需要更多信息吗?

如果您需要更多信息来理解我的问题,请告诉我。

.net c# expression expression-trees

1
推荐指数
1
解决办法
592
查看次数

lambda到表达式树

如何将以下lambda转换为表达式树?

source.Join(lookup, s => s.Id, l => l.Id, (s,l) => l)
Run Code Online (Sandbox Code Playgroud)

我认为除了resultSelector(s,l)=> l之外,我已经涵盖了所有内容.

这是我的代码..谢谢!

public static IQueryable<TLookup> GetLookupSource<T, TLookup, TKey>(this IQueryable<T> source, IQueryable<TLookup> lookup{
   ParameterExpression s = Expression.Parameter(source.ElementType, "s");
   Expression<Func<T, TKey>> outerKeySelector = Expression.Lambda<Func<T, TKey>>(Expression.PropertyOrField(s, "Id"), s);

   ParameterExpression l = Expression.Parameter(lookup.ElementType, "l");
   Expression<Func<TLookup, TKey>> innerKeySelector = Expression.Lambda<Func<TLookup, TKey>>(Expression.PropertyOrField(l, "Id"), l);

   Expression<Func<T, TLookup, IQueryable<TLookup>>> resultSelector = null;//<---How to compose this

   MethodInfo joinMethod = typeof(Queryable).GetMethods(BindingFlags.Static | BindingFlags.Public).Where(m => m.Name == "Join" && m.GetParameters().Length == 5).First();
   var genericJoinMethod = joinMethod.MakeGenericMethod(typeof(T), typeof(TLookup), typeof(TKey), typeof(IQueryable<TLookup>)); …
Run Code Online (Sandbox Code Playgroud)

c# expression-trees

1
推荐指数
1
解决办法
397
查看次数

Linq到sql表达式树执行区问题

我有一个问题,想知道是否有办法吃蛋糕并吃掉它.

目前我有一个存储库和查询样式模式,我如何使用Linq2Sql,但我有一个问题,我看不到一个很好的方法来解决它.以下是问题的示例:

var someDataMapper = new SomeDataMapper();
var someDataQuery = new GetSomeDataQuery();
var results = SomeRepository.HybridQuery(someDataQuery)
                            .Where(x => x.SomeColumn == 1 || x.SomeColumn == 2)
                            .OrderByDescending(x => x.SomeOtherColumn)
                            .Select(x => someDataMapper.Map(x));

return results.Where(x => x.SomeMappedColumn == "SomeType");
Run Code Online (Sandbox Code Playgroud)

这里要注意的主要部分是Mapper,Query,Repository,然后是最后的where子句.我这样做是作为一个更大的重构的一部分,我们发现有很多类似的查询得到稍微不同的结果集,但然后将它们以相同的方式映射到特定于域的模型.因此,例如,取回a tbl_car然后将其映射到Car对象.因此,映射器基本上采用一种类型并吐出另一种类型,因此与选择中通常发生的情况完全相同:

// Non mapped version
select(x => new Car 
{
    Id = x.Id,
    Name = x.Name,
    Owner = x.FirstName + x.Surname
});

// Mapped version
select(x => carMapper.Map(x));
Run Code Online (Sandbox Code Playgroud)

因此,汽车映射器在所有区域上都可以重复使用,这些区域执行类似的查询,返回相同的最终结果,但在此过程中执行不同的位.但是我一直得到错误,说Map无法转换为SQL,这很好,因为我不希望它,但是我理解,因为它在表达式树中它会尝试转换它.

{"Method 'SomeData Map(SomeTable)' has no supported translation to SQL."}
Run Code Online (Sandbox Code Playgroud)

最后,返回并映射的对象在堆栈中进一步传递给其他对象使用,这使用Linq …

c# sql linq expression-trees linq-to-sql

1
推荐指数
1
解决办法
265
查看次数

从另一个表达式构建索引表达式

脚本

public class Element {
   public int Id {get;set;}
}

public class ViewModel {
   public IList<Element> Elements{get;set;}
}
Run Code Online (Sandbox Code Playgroud)

我有一个类型参数的方法Expression<Func<Element, int>>,看起来像m => m.Id

我想改造

m => m.Id (其中m是元素)

x => x.Elements[0].Id 其中x是ViewModel,0是"index"参数

我现在拥有的(当然是通用的,为了清晰起见我删除了通用部分)

public static class Helpers {
    public static Expression<Func<ViewModel, int>> BuildExpressionArrayFromExpression(
                this Expression<Func<Element, int>> expression,
                ViewModel model,
                int index = 0, 
                string bindingPropertyName = "Elements"//the name of the "List" property in ViewModel class
                ) 
    {
       var parameter = Expression.Parameter(typeof(ViewModel), "x");
       var viewModelProperty = model.GetType().GetProperty(bindingPropertyName);
       Expression …
Run Code Online (Sandbox Code Playgroud)

c# asp.net-mvc lambda expression-trees

1
推荐指数
1
解决办法
1538
查看次数

将Func <Type,object>表达式转换为Func <T>,其中T是通用约束

我有这个静态功能

public static object Create(Type t)
{
    //unimportant
}
Run Code Online (Sandbox Code Playgroud)

我无法控制上面的上述功能,所以我无法改变它.问题是它不是通用的,所以我必须将返回的对象转换为某种类型.这个类型是由我调用该Create方法的另一个泛型类的约束提供的.

这是我到达的地方:

public static class Creator<T>
{
    public static void Create()
    {
        var m = typeof(SomeClass).GetMethod("Create");
        var p = Expression.Parameter(typeof(Type));
        var e = Expression.Call(m, p);

        //at this stage I want to create delegate for calling the 'Create' method, 
        //then pass typeof(T) as parameter, get returned object, 
        //and finally cast it to 'T'.

        //for eg, I can do it like this:
        var f = Expression.Lambda<Func<Type, object>>(e, p).Compile();
        Func<T> mainThing …
Run Code Online (Sandbox Code Playgroud)

c# generics typeconverter expression-trees

1
推荐指数
1
解决办法
1490
查看次数

List <T>是表达式树中的常量,表达式参数还是其他什么?

假设我有这个lambda表达式,我想写一个表达式Tree:

query.Where(d => (allCk && d.FacilityId == facilityId) //1.
      ||
     (!allCk && allSelected && d.FacilityId == facilityId  && !ids.Contains(d.Id)) //2.
      ||
     (!allCk && !allSelected && ids.Contains(d.Id))) //3.
Run Code Online (Sandbox Code Playgroud)

这就是我设法写它的原因:为简洁起见,我只展示第二个条件,这是最复杂的条件(!allCk && allSelected && d.FacilityId == facilityId && !ids.Contains(d.Id)).

private Expression<Func<Documents, bool>> GetDocumentsPredicate(
        int facilityId, bool allCk, bool allSelected, List<int> ids)
{
  ParameterExpression pe = Expression.Parameter(typeof(Documents), "d");

  var listExpr1 = new List<Expression>();
  listExpr1.Add(Expression.IsFalse(Expression.Constant(allCk)));  //allCk
  listExpr1.Add(Expression.Constant(allSelected));                //allSelected

  var facilityParam = Expression.Constant(facilityId);            //facility
  Expression facilityIdProp = Expression.Property(pe, "FacilityId");
  Expression facilityIdEql = Expression.Equal(facilityIdProp, facilityParam); …
Run Code Online (Sandbox Code Playgroud)

c# linq expression-trees

1
推荐指数
1
解决办法
330
查看次数

Lambda表达式 - C#编译器推断

我试图了解编译器推断行为.例如,从下面的代码片段中,编译的委托的运行时类型是Func<int>

Expression addExpr = Expression.Add(Expression.Constant(2), Expression.Constant(1));
LambdaExpression lambdaExpr1 = Expression.Lambda(addExpr, null);
var compiled = lambdaExpr1.Compile();
Run Code Online (Sandbox Code Playgroud)

但是下面的代码行不能编译.不确定这里有什么含糊不清的编译器隐式转换它Expression<Func<int>>并赋值给LambdaExpression类型

LambdaExpression lambdaExp2 = ()=>2+1;
Run Code Online (Sandbox Code Playgroud)

我可以猜到右边的lambda表达式的一个可能原因也可以匹配我的自定义委托的签名,在这种情况下,编译器无法推断委托类型.但同样的原因适用于我的初始代码段.为什么CLR(运行时)可以决定它可以是类型Func<int>.如果这是可能的并且通过运行时足够的推断那么为什么c#编译器也可以做同样的事情.

c# type-inference expression-trees

1
推荐指数
1
解决办法
244
查看次数

表达式获取数组的长度

如果你有一个Type of Type Array而不是一个特定的数组类型,比如int [],那么如何生成一个表达式,该表达式可以快速获取长度,而无需执行整个属性获取malarkay.

例如在下面

ParameterExpression para3 = Expression.Parameter(typeof(int[]), "p3");
ParameterExpression para4 = Expression.Parameter(typeof(Array), "p4");

Type pt1 = para3.Type.GetElementType();
Type pt2 = para4.Type.GetElementType();

MethodInfo mArrayLength = Strong.Instance<Array>.Property<int>(a => a.Length).GetGetMethod();

Expression asdf5 = Expression.ArrayLength(para3);
Expression asdf6 = Expression.ArrayLength(para4);
Expression asdf7 = Expression.Call(para4, mArrayLength);
Run Code Online (Sandbox Code Playgroud)

mArrayLength只是Array类型的Length属性的get方法.

这里的表达式为asdf5,因为para5的类型为int [],但asdf6 不起作用,因为para6的类型只是Array类型.asdf7确实有效.

我想要的是有效地使用ldlen指令,它只需要一个Object,而不是调用一个方法.这仅仅是表达式树库的限制吗?

您可以使用反射编辑该字段,甚至可以编译表达式!但是尝试运行委托将导致操作可能破坏运行时异常的稳定性.

Array parr = new int[5];

Expression pArraylength = Expression.ArrayLength(para3);
pOperandFieldInfo.SetValue(pArraylength, para4);

Expression<Func<Array, int>> pexchanger = (Expression<Func<Array, int>>)Expression.Lambda(pArraylength, para4);
Func<Array, int> pFunc = pexchanger.Compile();
int pint = pFunc(parr);
Run Code Online (Sandbox Code Playgroud)

c# arrays cil expression-trees

1
推荐指数
1
解决办法
150
查看次数

如何表达All with Expression Trees

对于给定的搜索标签过滤器,预期结果是表示在给定标签ID列表中具有所有标签的实体的表达式.

Lambda可能将此表达为:

class Tag 
{
   public long TagId { get; set; }
}

class Taggable 
{
   ICollection<Tag> Tags { get; set; }
}

...

IEnumerable<long> searchTags = new List<long>() { 1, 2, 3 };
Func<Taggable, bool> filter = taggable => searchTags.All(qtag => taggable.Tags.Any(tag => tag.TagId == qtag));
Run Code Online (Sandbox Code Playgroud)

尝试将此表示为表达式树失败:

var tagParam = Expression.Parameter(typeof(Tag), "tag");    
var taggableParam = Expression.Parameter(typeof(Taggable), "taggable");
MemberExpression tagsProperty = Expression.Property(taggableParam, "Tags");
ConstantExpression searchTagsConstant = Expression.Constant(searchTags);

var containsCall = Expression.Call(
      typeof(Enumerable), "Contains",
      new[] { typeof(long) },
      searchTagsConstant,
      Expression.Property(tagParam, "TagID") …
Run Code Online (Sandbox Code Playgroud)

c# linq expression-trees

1
推荐指数
1
解决办法
121
查看次数