2016-09-20 15 views
3

.NET 4.5 라이브러리를 .NETStandard v1.6으로 변환하는 중에 이전에 통과하지 못한 단위 테스트가 실패했습니다..NET Framework와 .NET Framework 간의 Expression.Subtract에 대한 차이점

이 식 트리가 .NET 4.5에 대한 컴파일하지만 발생
ParameterExpression arg1 = Expression.Parameter(typeof(DateTime), "arg1"); 
ParameterExpression arg2 = Expression.Parameter(typeof(DateTime), "arg2"); 
var test = Expression.Subtract(arg1, arg2); 

InvalidOperationException.NETStandard v1.6에서 :

가 진 운영자 빼기가 정의되어 있지

나는 코드의 다음 세 줄에 문제를 정확히 'System.DateTime'및 'System.DateTime'유형의 경우

그러나 모두 대상에 대해 다음과 같은 코드가 작동합니다

DateTime one = new DateTime(); 
DateTime two = new DateTime(); 
TimeSpan difference = one - two; 

내가 이렇게뿐만 아니라 .NET 코어에 대해 컴파일하는 식 트리를 기대? 내가 뭔가 잘못하고 있니, 아니면 is this a bug in .NET Core?

+0

같은 현상이 나타나는 상수 표현식 ('Expression.Constant (DateTime.Now)')을 사용해 보았습니다. –

+0

[소스 코드보기] (https://github.com/dotnet/corefx/blob/release/1.0.0-rc2/src/System.Linq.Expressions/src/System/Linq/Expressions/) BinaryExpression.cs # L758),'GetUserDefinedBinaryOperator'가'null '을 리턴하는 것으로 보입니다. –

답변

3

System.Linq.Expressions 어셈블리의 버그입니다.

이 방법은 빼기 연산자 방법을 찾는 데 사용됩니다

public static MethodInfo GetAnyStaticMethodValidated(this Type type, string name, Type[] types) 
{ 
    // Method name is "op_Subtraction" in your case 
    MethodInfo anyStaticMethod = type.GetAnyStaticMethod(name); 
    // DateTime and DateTime in your case 
    if (!anyStaticMethod.MatchesArgumentTypes(types)) 
    { 
     return null; 
    } 
    return anyStaticMethod; 
} 

public static MethodInfo GetAnyStaticMethod(this Type type, string name) 
{ 
    foreach (MethodInfo current in type.GetRuntimeMethods()) 
    { 
     if (current.IsStatic && current.Name == name) 
     { 
      return current; 
     } 
    } 
    return null; 
} 

당신이 볼 때, 대신 DateTime 두 가지가 있습니다 경우, 사용 가능한 모든 통해 반복의 무작위 GetAnyStaticMethod 추천 DateTime에서 첫 번째 "op_Subtraction"방법, 이러한 조작 방법 :

public static DateTime operator -(DateTime d, TimeSpan t); 
public static TimeSpan operator -(DateTime d1, DateTime d2); 

그래서 코드가 DateTimeTimeSpan에 걸리는 잘못 하나를 선택합니다, 그럼 그냥 입력 유형 때문에 실패 일치하지 않아.

.NET 4.5에서 그들은 인수 형식을 전달하여 적절한 방법으로 검색 할이 실제로 .NET 코어의 구현에 버그

Type[] types = new Type[] 
{ 
    leftType, // DateTime in your case 
    rightType // DateTime in your case 
}; 
BindingFlags bindingAttr = BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic; 
// Method name is "op_Subtraction" in your case 
MethodInfo methodInfo = nonNullableType.GetMethodValidated(name, bindingAttr, null, types, null); 
+0

굉장합니다. [github 프로젝트에 대한 정확한 문제보고] (https://github.com/dotnet/corefx/issues/11907)의 영광을드립니다. :) 나는 당신이 그 뒤에 정확한 이유를 발견했다는 것을 지적하기 위해 이슈를 업데이트 할 것이다. –

+1

아니면 포크로 커뮤니티에 기여할 수 있습니다. –

+0

실제 경험이없는 사람이 즉시 그것에 점프하면 나중에 고려해 볼 수 있습니다. 먼저 내 라이브러리를 계속 마이그레이션하고 싶습니다 (이에 대한 해결 방법 찾기 포함). :) –

3

입니다. 그 이유는 System.Linq.Expressions이 코어로 이식 될 때 .NET Core에서 특정 API를 사용할 수 없으므로 사용자 지정 구현이 개발 되었기 때문에이 API는 발견되지 않았습니다.

이 문제를 해결하려면 sent a PR to dotnet/corefx입니다. 호기심에 문제는 연산자를 찾는 메서드가 메서드를 통해 루프되지만 메서드가 원하는 메서드인지 확인하기 전에 루프가 일치하는 부분을 찾을 때마다 중단된다는 것입니다. 루프 내에서 매개 변수 검사를 이동하는 것이 수정되었습니다.

 internal static MethodInfo GetAnyStaticMethodValidated(
     this Type type, 
     string name, 
     Type[] types) 
    { 
     foreach (var method in type.GetRuntimeMethods()) 
     { 
      if (method.IsStatic && method.Name == name && method.MatchesArgumentTypes(types)) 
      { 
       return method; 
      } 
     } 
     return null; 
    } 
+0

여기 전체 코드베이스를 볼 수 없으므로 그렇게 확신하지는 않지만 이것을 수행하십시오 또한 반환 유형을 확인 하시겠습니까? 또는 반환 유형에 오버로드 할 수 없으므로이를 확인할 필요가 없습니다. :) 그냥 모든 각도를 다루는 당김 요청을 다시 확인하고 싶습니다. 이것이 이전에 잡히지 않았으므로 이것에 대한 단위 테스트를 추가하는 것도 흥미로울 수 있습니다. –

+0

오, 당신이 단위 테스트를 추가했는지 봅니다. 그래서이 코드는 아마도 DateTime - TimeSpan을 다루어야 할 것입니다. –

+1

감사합니다. 다른 단위 테스트를 추가했습니다. –