Skip to content

Commit

Permalink
Merge pull request #1 from carl-berg/feature/open-generics-support
Browse files Browse the repository at this point in the history
Supporting open generics
  • Loading branch information
carl-berg authored Mar 14, 2023
2 parents 16904b5 + 7a66238 commit e7bbd48
Show file tree
Hide file tree
Showing 10 changed files with 150 additions and 43 deletions.
34 changes: 34 additions & 0 deletions .github/workflows/build-and-test.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
name: Build and Test

on:
push:
branches: [ main ]
pull_request:
branches: [ main ]

env:
DOTNET_VERSION: '7.x' # The .NET SDK version to use

jobs:
build-and-test:
name: Test ${{ matrix.dotnet }} on ${{matrix.os}}
runs-on: ${{ matrix.os }}
strategy:
matrix:
dotnet: [ '3.1', '6.x', '7.x' ]
os: [windows-latest]

steps:
- uses: actions/checkout@v3
- uses: actions/setup-dotnet@v3
with:
dotnet-version: ${{ env.DOTNET_VERSION }}

- name: Install dependencies
run: dotnet restore

- name: Build
run: dotnet build --configuration Debug --no-restore

- name: Test
run: dotnet test --configuration Debug --no-restore --verbosity normal
49 changes: 49 additions & 0 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
name: Release ATypeScanner

on:
push:
tags:
- '*'

env:
DOTNET_VERSION: '7.x' # The .NET SDK version to use

jobs:

build-and-test:
name: Build and test
runs-on: windows-latest
steps:
- uses: actions/checkout@v3
- uses: actions/setup-dotnet@v3
with:
dotnet-version: ${{ env.DOTNET_VERSION }}

- name: Install dependencies
run: dotnet restore

- name: Test
run: dotnet test --configuration Release --no-restore --verbosity normal

deploy:
name: Deploy
runs-on: windows-latest
environment: NugetDeploy
needs: [build-and-test]
steps:
- uses: actions/checkout@v2
- uses: actions/setup-dotnet@v1
with:
dotnet-version: ${{ env.DOTNET_VERSION }}

- name: Package artifact
run: dotnet pack ATypeScanner/ATypeScanner.csproj --configuration Release -o ${{ github.workspace }}/artifact

- name: Upload artifact
uses: actions/upload-artifact@v2
with:
name: ATypeScanner
path: ${{ github.workspace }}/artifact/**/*

- name: Publish the package to nuget.org
run: dotnet nuget push ${{ github.workspace }}\artifact\*.nupkg -s https://api.nuget.org/v3/index.json -k ${{ secrets.NUGET_TOKEN }}
10 changes: 10 additions & 0 deletions ATypeScanner.Tests.Types/OpenTypes.cs
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,16 @@ public class OpenClassImplementation : OpenClass<AType>

}

public class GenericOpenInterfaceImplementation<T> : IOpenInterface<T> where T : AType
{

}

public class GenericOpenClassImplementation<T> : OpenClass<T> where T : AType
{

}

public class AType
{

Expand Down
9 changes: 5 additions & 4 deletions ATypeScanner.Tests/ATypeScanner.Tests.csproj
Original file line number Diff line number Diff line change
@@ -1,13 +1,14 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFramework>netcoreapp2.2</TargetFramework>
<TargetFramework>net7.0</TargetFramework>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="Shouldly" Version="3.0.2" />
<PackageReference Include="xunit" Version="2.4.1" />
<PackageReference Include="xunit.runner.visualstudio" Version="2.4.1">
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.5.0" />
<PackageReference Include="Shouldly" Version="4.1.0" />
<PackageReference Include="xunit" Version="2.4.2" />
<PackageReference Include="xunit.runner.visualstudio" Version="2.4.5">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
Expand Down
13 changes: 11 additions & 2 deletions ATypeScanner.Tests/TypeScannerTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,12 +12,21 @@ public class TypeScannerTests
public void CanResolveOpenInterfaceTypes()
{
var scanner = new TypeScanner(typeof(AType).Assembly);
var matches = scanner.FindClosingImplementationsOf(typeof(IOpenInterface<>));
var matches = scanner.FindClosingImplementationsOf(typeof(IOpenInterface<>)).ToList();
matches.ShouldNotBeEmpty();
matches.ShouldContain(p => p.ConcreteType == typeof(OpenInterfaceImplementation));
matches.ShouldContain(p => p.ConcreteType == typeof(OpenClassImplementation));
matches.ShouldAllBe(p => p.GenericType == typeof(IOpenInterface<AType>));

}

[Fact]
public void CanResolveGenericOpenTypes()
{
var scanner = new TypeScanner(typeof(AType).Assembly);
var matches = scanner.FindOpenImplementationsOf(typeof(IOpenInterface<>)).ToList();
matches.ShouldNotBeEmpty();
matches.ShouldContain(p => p.ConcreteType == typeof(GenericOpenInterfaceImplementation<>));
matches.ShouldContain(p => p.ConcreteType == typeof(GenericOpenClassImplementation<>));
}

[Fact]
Expand Down
7 changes: 4 additions & 3 deletions ATypeScanner.sln
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 16
VisualStudioVersion = 16.0.29123.88
# Visual Studio Version 17
VisualStudioVersion = 17.6.33417.168
MinimumVisualStudioVersion = 10.0.40219.1
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ATypeScanner", "ATypeScanner\ATypeScanner.csproj", "{74535BC4-A06A-48D4-BAB3-5EF10848A8B5}"
EndProject
Expand All @@ -11,8 +11,9 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ATypeScanner.Tests.Types",
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{F7675175-60B9-46E4-90E8-82EA34DEC7DB}"
ProjectSection(SolutionItems) = preProject
azure-pipeline.yml = azure-pipeline.yml
.github\workflows\build-and-test.yml = .github\workflows\build-and-test.yml
README.md = README.md
.github\workflows\release.yml = .github\workflows\release.yml
EndProjectSection
EndProject
Global
Expand Down
4 changes: 2 additions & 2 deletions ATypeScanner/ATypeScanner.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@

<PropertyGroup>
<TargetFramework>netstandard2.0</TargetFramework>
<Copyright>Copyright (c) 2019 Carl Berg</Copyright>
<VersionPrefix>0.1.1</VersionPrefix>
<Copyright>Copyright (c) 2023 Carl Berg</Copyright>
<Version>0.2.0</Version>
<Authors>Carl Berg</Authors>
<Description>An appeasing light weight type scanner</Description>
<PackageLicenseExpression>MIT</PackageLicenseExpression>
Expand Down
1 change: 1 addition & 0 deletions ATypeScanner/ITypeScanner.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ namespace ATypeScanner
public interface ITypeScanner
{
IEnumerable<ClosingTypeResult> FindClosingImplementationsOf(Type openType);
IEnumerable<ClosingTypeResult> FindOpenImplementationsOf(Type openType);
IEnumerable<Type> FindImplementationsOf<TType>();
IEnumerable<Type> FindImplementationsOf(Type typeToFind);
}
Expand Down
34 changes: 34 additions & 0 deletions ATypeScanner/TypeScanner.cs
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,40 @@ public IEnumerable<ClosingTypeResult> FindClosingImplementationsOf(Type openType
}
}

/// <summary>
/// Returns all generic classes that implement <paramref name="openType"/>
/// </summary>
public IEnumerable<ClosingTypeResult> FindOpenImplementationsOf(Type openType)
{
foreach (var assembly in _assemblies)
{
foreach (var type in assembly.DefinedTypes)
{
if (type.IsInterface)
{
continue;
}
else if (type.IsGenericType)
{
if (openType.IsInterface)
{
foreach (var @interface in type.GetInterfaces())
{
if (@interface.IsGenericType && openType.IsAssignableFrom(@interface.GetGenericTypeDefinition()))
{
yield return new ClosingTypeResult(@interface, type.AsType());
}
}
}
else if (openType != type && MatchClassType(openType, type) is Type matchingType)
{
yield return new ClosingTypeResult(matchingType, type);
}
}
}
}
}

/// <summary>
/// Returns all classes that implement <typeparamref name="TType"/>
/// </summary>
Expand Down
32 changes: 0 additions & 32 deletions azure-pipeline.yml

This file was deleted.

0 comments on commit e7bbd48

Please sign in to comment.