Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

No longer crash when trying to match a generic method that'll violate the generic constraints #274

Merged
merged 3 commits into from
Feb 14, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 6 additions & 6 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,10 @@ jobs:
uses: actions/setup-dotnet@v1
with:
dotnet-version: '3.1.x'
- name: Setup .NET Core 5.0
- name: Setup .NET 7.0
uses: actions/setup-dotnet@v1
with:
dotnet-version: '5.0.x'
dotnet-version: '7.0.x'
- name: Setup gitversion
run: dotnet tool install --global GitVersion.Tool
- name: Calculate version
Expand All @@ -34,16 +34,16 @@ jobs:
run: dotnet build DynamicExpresso.sln --no-restore -c Release /p:Version=${{steps.calc_version.outputs.PROJECT_VERSION}}
- name: Test .net core 3.1
run: dotnet test DynamicExpresso.sln --no-build --no-restore -c Release --verbosity normal -f netcoreapp3.1
- name: Test .net core 5.0
run: dotnet test DynamicExpresso.sln --no-build --no-restore -c Release --verbosity normal -f netcoreapp5.0
- name: Test .net core 7.0
run: dotnet test DynamicExpresso.sln --no-build --no-restore -c Release --verbosity normal -f net7.0
test-win:
runs-on: windows-2019
steps:
- uses: actions/checkout@v2
- name: Setup .NET Core 5.0
- name: Setup .NET 7.0
uses: actions/setup-dotnet@v1
with:
dotnet-version: '5.0.x'
dotnet-version: '7.0.x'
- name: Restore packages
run: dotnet restore DynamicExpresso.sln
- name: Build
Expand Down
21 changes: 18 additions & 3 deletions src/DynamicExpresso.Core/Parsing/Parser.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,13 @@
using System.Collections;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Dynamic;
using System.Globalization;
using System.Linq;
using System.Linq.Expressions;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Security;
using System.Text;
using DynamicExpresso.Exceptions;
using DynamicExpresso.Resources;
Expand Down Expand Up @@ -2361,7 +2361,18 @@ private static MethodInfo MakeGenericMethod(MethodData method)
.Select(p => actualGenericArgs.TryGetValue(p.Name, out var typ) ? typ : typeof(object))
.ToArray();

return methodInfo.MakeGenericMethod(genericArgs);
MethodInfo genericMethod = null;
try
{
genericMethod = methodInfo.MakeGenericMethod(genericArgs);
}
catch (ArgumentException e) when (e.InnerException is VerificationException)
{
// this exception is thrown when a generic argument violates the generic constraints
return null;
}

return genericMethod;
}

private static Dictionary<string, Type> ExtractActualGenericArguments(
Expand Down Expand Up @@ -2398,8 +2409,12 @@ private static Dictionary<string, Type> ExtractActualGenericArguments(
}
else
{
var innerGenericTypes = ExtractActualGenericArguments(requestedType.GetGenericArguments(), actualType.GetGenericArguments());
var requestedInnerGenericArgs = requestedType.GetGenericArguments();
var actualInnerGenericArgs = actualType.GetGenericArguments();
if (requestedInnerGenericArgs.Length != actualInnerGenericArgs.Length)
continue;

var innerGenericTypes = ExtractActualGenericArguments(requestedInnerGenericArgs, actualInnerGenericArgs);
foreach (var innerGenericType in innerGenericTypes)
extractedGenericTypes[innerGenericType.Key] = innerGenericType.Value;
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFrameworks>net5.0;netcoreapp3.1;net462</TargetFrameworks>
<TargetFrameworks>net7.0;net5.0;netcoreapp3.1;net462</TargetFrameworks>

<IsPackable>false</IsPackable>
</PropertyGroup>
Expand Down
15 changes: 15 additions & 0 deletions test/DynamicExpresso.UnitTest/MemberInvocationTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -328,8 +328,18 @@ public void Method_with_generic_param()
Assert.AreEqual(x.MethodWithGenericParamAndDefault1Levels(y), target.Eval("x.MethodWithGenericParamAndDefault1Levels(y)", parameters));
Assert.AreEqual(x.MethodWithGenericParamAndDefault2Levels(y), target.Eval("x.MethodWithGenericParamAndDefault2Levels(y)", parameters));
Assert.AreEqual(x.MethodWithGenericParamAndDefault2Levels(y, w), target.Eval("x.MethodWithGenericParamAndDefault2Levels(y, w)", parameters));
}

[Test]
public void Method_with_generic_constraints()
{
var target = new Interpreter();

var x = new MyTestService();
target.SetVariable("x", x);

Assert.AreEqual("works", target.Eval("x.GenericMethodWithConstraint(\"works\")"));
Assert.Throws<NoApplicableMethodException>(() => target.Eval("x.GenericMethodWithConstraint(5)"), "This shouldn't throw a System.ArgumentException \"Violates the constraint of type 'T'\"");
}

[Test]
Expand Down Expand Up @@ -646,6 +656,11 @@ public long OverloadMethodWithParamsArray(params long[] paramsArray)
{
return paramsArray.Max();
}

public T GenericMethodWithConstraint<T>(T input) where T : class
{
return input;
}
}

private class MyTestServiceCaseInsensitive
Expand Down