Alternative to nested type of type Expression

2019-01-18 18:50发布

问题:

I have a function used when calling a service. Before it call the service, it will create a log entry:

protected TResult CallService<TService, TResult>(TService service,
    Expression<Func<TService, TResult>> functionSelector)
{
    Logger.LogServiceCall(service, functionSelector);
    return functionSelector.Compile()(service);
}

The Visual Studio 2010 Code Analyzer informs me that I shouldn't use Nested Type in the following message:

CA1006 : Microsoft.Design : Consider a design where 'ServiceManager.CallService<TService, Result>(TService, Expression<Func<TService, TResult>>)' doesn't nest generic type 'Expression<Func<TService, TResult>>'.

While I could simply create a suppression rule for this entry, is there is an alternative that exist that would prevent displaying such warning?

回答1:

I would suppress it in this case, with the reason that the caller doesn't have to cope with nested generics, he is just passing a lambda expression, which is easy to use.

CA does not make exceptions for lambda expressions. Sometimes It is better to suppress it then to write weird code.



回答2:

I'll be honest, I suppress that rule most of the time. While I can understand that some of the construction of the nested types can be avoided, it is more often than not the case; you usually want to leave that to the call site because you can't guarantee that the call site will want the nested generic type to be instantiated in the same way.

This is one of those rules that I find a bit overbearing; I generally agree with most of them, but not this one.



回答3:

Methods like yours are used extensively in Linq, for example:

public static IQueryable<TSource> Where<TSource>(this IQueryable<TSource> source, 
    Expression<Func<TSource, bool>> predicate)

The alternative would be to declare a delegate type to replace the nested Func<TService, TResult>, but that's just as likely to confuse a more experienced developer who's used to working with expression trees.

Microsoft obviously makes an exception to CA1006 for nested generic expression types, and so should we.



回答4:

You can suppress the message warning with SuppressMessageAttribute.

[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design","CA1006:<rule name>")]
protected TResult CallService<...Snip...