2017-04-19 18 views
2

我今天有一个静态函数,我通过房产表达,我从它创建一个字符串:传递兰巴表达式列表访问属性

public static string SomeFunction<TModel, TProperty>(TModel model, Expression<Func<TModel, TProperty>> expression){...} 

我想改变它来处理列表这样的表达式:

static string SomeFunctionForList<TModel, TProperty>(TModel model, List<Expression<Func<TModel, TProperty>>> expressions){...} 

在第二种情况下,我会循环表达式并执行我在其上执行的任何逻辑。

这就是我现在如何调用该函数:

SomeFunction(this, m => m.nameOfProperty) 

我如何调用该函数,定义表达式的一个列表?我想这一点,但它不工作:

SomeFunctionForList(this, 
        new List<Expression<Func<TModel, TProperty>>> { 
         { m => m.nameOfProperty1}, 
         { m => m.nameOfProperty2} 
}); 

我收到的TModel和TProperty无法找到一个编译器错误。清楚的是,这在另一个文件中被调用。

+0

我不知道,但我的意思是“TModel的”和“TProperty”不是类型。它们是通用参数。你必须用任何模型类型替换“TModel”,用任何属性类型替换“TProperty”。 –

+0

您遇到的问题是每个产权的“TProperty”都会有所不同? – DavidG

+0

耶 - 基本上,我想发送一个模型和一个lamba表达式列表,并让该方法发挥其魔力 – Corez

回答

1

你有一般方法SomeFunctionForList与通用类型参数TModelTProperty。在第一种情况下,类型推断能够从方法调用的第一个和第二个参数中推断出这些参数的类型。这就是为什么你可以直接跳过指定类型参数。

但类型推断仅适用于泛型方法。它不适用于从构造函数参数推断类型参数。这就是为什么你应该明确指定List<T>泛型参数。注意:您应该指定类型名称而不是通用参数。例如。如果TModelYourModel类,和两个属性有string类型,然后调用方法应该是这样的:

SomeFunctionForList(this, 
      new List<Expression<Func<YourModel, string>>> { 
        { m => m.nameOfProperty1}, 
        { m => m.nameOfProperty2} 
      }); 

所以,列表构造函数的用法是不是如果你想使用类型推断一个不错的选择。您可以使用params指定数目可变的参数(这是作为一个数组传递),并有类型推断的好处:

public static string SomeFunction<TModel, TProperty>(
    TModel model, params Expression<Func<TModel, TProperty>>[] expressions) 

随后的方法调用看起来像

SomeFunctionForList(this, 
       m => m.nameOfProperty1, 
       m => m.nameOfProperty2 
      ); 

注意,性能应有相同的类型。

+0

Gotcha - 在现实生活中,我有几个参数后,在方法中的所以参数不是一个理想的选择。有什么办法可以欺骗编译器进行跳过类型推断吗? – Corez

+1

@Corez你不能使用构造函数 - 类型推断在这里不起作用。您可以创建工厂,通过一般方法为您创建清单。同样的方法用于元组 - 而不是调用'新元组(4,“foo”)''你可以调用工厂方法'Tuple.Create(4,“foo”)'。你的工厂可以简单的作为'公共静态列表 CreateList (params T [] items)=> items.ToList();'和用法将'SomeFunctionForList(this,Factory.CreateList(m => m.nameOfProperty1,m => m.nameOfProperty2))' –

0
public static string SomeFunction<TModel, TProperty>(TModel model, params Expression<Func<TModel, TProperty>>[] expressions) 
+0

我应该已经更清楚了 - 我的意思是当我调用该函数时发生该问题。在那个文件中,它不能识别TModel和TPropoerty – Corez

+0

你必须打开这些方法,并使用反射来计算通用参数,以便成功地调用它们。 如果没有方法源代码,很难猜测错误。但我认为你应该能够通过反思做到这一点。 –

+0

错误是一个编译错误,调用者无法编译,因为无法找到TModel和TProperty。很明显,因为它们是调用代码范围之外的泛型。 – Corez

1

“TModel”和“TProperty”是通用参数,不是类型。但是如果你想调用它,你必须输入任何模型类型和任何属性类型。

例如,这应该工作:

private string aStringProperty { get; set; } 
private int aIntegerProperty { get; set; } 

-

SomeFunctionForList(this, new List<Expression<Func<Program, dynamic>>>{ 
                   { m => m.aStringProperty}, 
                   { m => m.aIntegerProperty} 
                  }); 

在我的情况,我用了一个动态的属性。有了这个,你可以使用不同类型的属性,但要小心!

1

您需要指定类型的参数,例如:

​​

但是,这仅允许您使用所有返还相同种类,在这种情况下string性能。你可以使用object代替:

SomeFunctionForList(t, 
       new List<Expression<Func<Thing, object>>> { 
        { m => m.StringProperty}, 
        { m => m.BoolProperty} 
});