Question

I have the following extension method which asserts that a property (Id) contains a specified attribute (TV):

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

The method can be called like this:

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

Compiles just fine. I was wondering if it is possible to remove T and TT from the method signature. T because ShouldHave is called on T why it shouldn't be necessary to specify it explicitly. And TT is the type of the property referenced in the expression (x.Id).

Was it helpful?

Solution

Automatic inference of type arguments only works if no generic arguments are specified in the method call. I.e., this:

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

is not valid syntax. You can either have "all or nothing".

Thus, if you want to infer T and TT, you need to pass the information currently contained in TV in some other way. For example, one option would be to pass the type of the attribute as a parameter:

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

(Obviously, this will require changes in your implementation of ShouldHave).

Then you should be able to call the method like this:

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

OTHER TIPS

The following compiles:

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

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

This omits the TV type argument, which is the reason for your need to explicitly specify the generic arguments at the call site. If you need this argument then you’re out of luck.

Try this:

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

You should find that exp now consists of the real expression surrounded by a cast to object. Inside your method, strip off the cast as follows:

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

Then you can start analysing the expression. You will have to do more runtime tests and safety checks than your original method though.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top