避免泛型参数

时间:2011-06-14 10:49:43

标签: c# generics extension-methods expression func

我有以下扩展方法断言属性(Id)包含指定的属性(TV):

public static void ShouldHave<T, TV, TT>(this T obj, Expression<Func<T, TT>> exp) {...}

可以像这样调用该方法:

MyDto myDto = new MyDto();
myDto.ShouldHave<MyDto, RequiredAttribute, int>(x => x.Id);

编译得很好。我想知道是否可以从方法签名中删除T和TT。因为在T上调用了ShouldHave,为什么不必明确指定它。 TT是表达式(x.Id)中引用的属性的类型。

3 个答案:

答案 0 :(得分:2)

以下编译:

public static void ShouldHave<T, TT>(this T obj, Expression<Func<T, TT>> exp)
{...}

MyDto myDto = new MyDto();
myDto.ShouldHave(x => x.Id);

这省略了TV类型参数,这是您需要在调用站点显式指定泛型参数的原因。如果你需要这个论点,那你就不走运了。

答案 1 :(得分:1)

只有在方法调用中指定了 no 泛型参数时,才能自动推断类型参数。即,这个:

myDto.ShouldHave<, RequiredAttribute, >(x => x.Id);

是无效的语法。你可以“全有或全无”。

因此,如果您想推断TTT,则需要以其他方式传递TV中当前包含的信息。例如,一个选项是将属性的类型作为参数传递:

public static void ShouldHave<T, TT>(this T obj, 
                                     Expression<Func<T, TT>> exp, 
                                     Type attribute) {...}

(显然,这需要更改ShouldHave的实现)。

然后你应该能够调用这样的方法:

MyDto myDto = new MyDto();
myDto.ShouldHave(x => x.Id, typeof(RequiredAttribute));

答案 2 :(得分:0)

试试这个:

public static void ShouldHave<TV>(this object obj, Expression<Func<object, object>> exp) {...}

你应该会发现exp现在包含一个由强制转换为对象的真实表达式。在你的方法中,剥离演员表如下:

Expression realExp = ((UnaryExpression) exp).Operand;

然后你就可以开始分析表达了。但是,您必须进行比原始方法更多的运行时测试和安全检查。