2013-02-18 40 views
2

我已经获得了一个扩展类,它实现了具有违反CA1006的签名的以下成员:DoNotNestGenericTypesInMemberSignatures规则。不要在成员签名中嵌套泛型类型

下面包含警告提到的代码。

我应该如何重构代码来解决CA1006警告?

请记住,我并不是很熟悉表达式树,尽管我对匿名方法,委托和lambdas有很好的理解。

任何帮助将不胜感激。

public static DataServiceQuery<TElement> Expand<TElement, TPropType>(this DataServiceQuery<TElement> source, Expression<Func<TElement, TPropType>> propertySelector) 
    { 
     string includeString = BuildString(propertySelector); 
     return source.Expand(includeString); 
    } 

    private static string BuildString(Expression propertySelector) 
    { 
     switch (propertySelector.NodeType) 
     { 
      case ExpressionType.Lambda: 
       LambdaExpression lambdaExpression = (LambdaExpression)propertySelector; 
       return BuildString(lambdaExpression.Body); 

      case ExpressionType.Quote: 
       UnaryExpression unaryExpression = (UnaryExpression)propertySelector; 
       return BuildString(unaryExpression.Operand); 

      case ExpressionType.MemberAccess: 

       MemberExpression memberExpression = (MemberExpression)propertySelector; 
       MemberInfo propertyInfo = memberExpression.Member; 

       if (memberExpression.Expression is ParameterExpression) 
       { 
        return propertyInfo.Name; 
       } 
       else 
       { 
        // we've got a nested property (e.g. MyType.SomeProperty.SomeNestedProperty) 
        return BuildString(memberExpression.Expression) + "/" + propertyInfo.Name; 
       } 

      case ExpressionType.Call: 
       MethodCallExpression methodCallExpression = (MethodCallExpression)propertySelector; 
       if (IsSubInclude(methodCallExpression.Method)) // check that it's a SubInclude call 
       { 
        // argument 0 is the expression to which the SubInclude is applied (this could be member access or another SubInclude) 
        // argument 1 is the expression to apply to get the included property 
        // Pass both to BuildString to get the full expression 
        return BuildString(methodCallExpression.Arguments[0]) + "/" + 
          BuildString(methodCallExpression.Arguments[1]); 
       } 
       // else drop out and throw 
       break; 
     } 
     throw new InvalidOperationException("Expression must be a member expression or an SubInclude call: " + propertySelector.ToString()); 

    } 

    private static readonly MethodInfo[] SubIncludeMethods; 
    static MyExtensions() 
    { 
     Type type = typeof(MyExtensions); 
     SubIncludeMethods = type.GetMethods().Where(mi => mi.Name == "SubExpand").ToArray(); 
    } 

    private static bool IsSubInclude(MethodInfo methodInfo) 
    { 
     if (methodInfo.IsGenericMethod) 
     { 
      if (!methodInfo.IsGenericMethodDefinition) 
      { 
       methodInfo = methodInfo.GetGenericMethodDefinition(); 
      } 
     } 
     return SubIncludeMethods.Contains(methodInfo); 
    } 

    public static TPropType SubExpand<TSource, TPropType>(this Collection<TSource> source, Expression<Func<TSource, TPropType>> propertySelector) 
     where TSource : class 
     where TPropType : class 
    { 
     throw new InvalidOperationException("This method is only intended for use with DataServiceQueryExtensions.Expand to generate expressions trees"); // no actually using this - just want the expression! 
    } 

    public static TPropType SubExpand<TSource, TPropType>(this TSource source, Expression<Func<TSource, TPropType>> propertySelector) 
     where TSource : class 
     where TPropType : class 
    { 
     throw new InvalidOperationException("This method is only intended for use with DataServiceQueryExtensions.Expand to generate expressions trees"); // no actually using this - just want the expression! 
    } 
+0

你可以给这个代码的例子被使用?看到错误的位置很复杂,有点棘手 – DiskJunky 2013-02-18 21:03:54

+0

是指公共方法的propertySelector参数吗?警告是关于使一个方法的接口可用 - 但是对于表达式,我没有看到它是如何被重构的,除非您将表达式参数包装在一个类中,该类将其作为属性或方法调用的返回提供。 – Jay 2013-02-18 21:07:45

+1

DiskJunky,感谢您对帮助解决此问题感兴趣。基本上,这些代码正在用来构建如下所示的lambda表达式。 var scenarioGroups = from scenarioGroup in ctx.ScenarioGroups.Expand(scenarioGroup => scenarioGroup.Scenarios.SubExpand(sc => sc.XYLines.SubExpand(xy => xy.Points)))其中... – 2013-02-19 14:05:56

回答

7

该警告是一个普遍的警告,应该帮助您设计一个更好,更简单的公共接口。在这种情况下,您会收到关于在方法中使用Expression<Func<TElement, TPropType>>参数的警告。但是,对于此方法,简化类型没有意义,而应该使用attribute来取消警告,或者从规则集中完全删除规则。


是一个愚蠢的例子,你或许应该考虑规则的建议以下是这样的方法:

public void F(Dictionary<String, List<Tuple<String, Int32>>> dictionary); 
+0

感谢您的帮助马丁。我相信你是对的。显而易见,尝试和简化类型是毫无意义的。我只需要压制它。 – 2013-02-19 14:13:48

+2

保持这个警告一段时间后,我压制它,因为它造成了太多的噪音。发现99%的时间使用“深度”为1(T >)的嵌套泛型类型是合法的。等待规则被改进以仅触发起始深度为2(T >>),这将更有意义;) – darkey 2013-06-04 04:52:55