AdvancedGenericTypeConstraints.Abstractions
0.2.0
See the version list below for details.
dotnet add package AdvancedGenericTypeConstraints.Abstractions --version 0.2.0
NuGet\Install-Package AdvancedGenericTypeConstraints.Abstractions -Version 0.2.0
<PackageReference Include="AdvancedGenericTypeConstraints.Abstractions" Version="0.2.0" />
<PackageVersion Include="AdvancedGenericTypeConstraints.Abstractions" Version="0.2.0" />
<PackageReference Include="AdvancedGenericTypeConstraints.Abstractions" />
paket add AdvancedGenericTypeConstraints.Abstractions --version 0.2.0
#r "nuget: AdvancedGenericTypeConstraints.Abstractions, 0.2.0"
#:package AdvancedGenericTypeConstraints.Abstractions@0.2.0
#addin nuget:?package=AdvancedGenericTypeConstraints.Abstractions&version=0.2.0
#tool nuget:?package=AdvancedGenericTypeConstraints.Abstractions&version=0.2.0
AdvancedGenericTypeConstraints
AdvancedGenericTypeConstraints enables compile-time-like validation for generic type rules in C# by combining lightweight attributes with a Roslyn analyzer.
Why this exists
Native C# generic constraints cannot express rules like:
- the supplied type must implement
IHandleMessages<T>for someT - the supplied type must carry a specific attribute
- one generic type argument must come from an assembly whose name is derived from another type argument's assembly
This project closes that gap with:
- a small abstractions package that exposes declarative attributes
- a Roslyn analyzer package that validates supplied type arguments at compile time
Packages
Install both packages in the consuming project:
<ItemGroup>
<PackageReference Include="AdvancedGenericTypeConstraints.Abstractions" Version="0.2.0" />
<PackageReference Include="AdvancedGenericTypeConstraints.Analyzers" Version="0.2.0" PrivateAssets="all" />
</ItemGroup>
Example
using AdvancedGenericTypeConstraints;
[AttributeUsage(AttributeTargets.Class)]
public sealed class ServiceAttribute : Attribute;
public interface IHandleMessages<TMessage>;
public interface IFeatureRegistry
{
void RegisterMessageHandler<
[MustImplementOpenGeneric(typeof(IHandleMessages<>))]
[MustHaveAttribute(typeof(ServiceAttribute))]
TMessageHandler>();
void RegisterServiceContract<
[MustMatchAssemblyNameOf(nameof(TImplementation), suffix: ".Contracts")]
TService,
TImplementation>();
}
Available checks
The current API supports:
MustImplementOpenGenericAttributeMustImplementOpenGenericAttribute(Type openGenericType, bool exactlyOne)MustNotImplementOpenGenericAttributeMustHaveAttributeAttributeMustMatchAssemblyNameOfAttribute
Diagnostic IDs
The analyzer currently emits these diagnostics:
AGTC001: required open generic type is missingAGTC002: forbidden open generic type is presentAGTC003: required open generic type is not matched exactly onceAGTC004: invalidMustImplementOpenGenericconfiguration on a generic parameterAGTC005: required attribute is missingAGTC006: assembly naming rule between two type arguments is violatedAGTC007:MustMatchAssemblyNameOfreferences an invalid generic parameter
Matching semantics
Open generic checks
The analyzer compares open generic type definitions, not closed constructed types.
A type counts as a match when the configured open generic type definition appears on:
- the concrete type argument itself
- any base type in its inheritance chain
- any implemented interface
Attribute checks
MustHaveAttributeAttribute checks whether the supplied type argument is directly annotated with the configured
attribute type. Derived attributes also satisfy the rule.
Assembly naming checks
MustMatchAssemblyNameOfAttribute compares simple assembly names.
For a declaration like:
void RegisterServiceContract<
[MustMatchAssemblyNameOf(nameof(TImplementation), suffix: ".Contracts")]
TService,
TImplementation>();
the analyzer requires TService to come from an assembly named:
{AssemblyOf(TImplementation)} + ".Contracts"
You can also configure:
prefixsuffixAllowedTypesas an explicit whitelist for legacy exceptions
Example:
void RegisterServiceContract<
[MustMatchAssemblyNameOf(
nameof(TImplementation),
suffix: ".Contracts",
AllowedTypes = new Type[] { typeof(ICelestialPostService), typeof(IOrbitalEchoStore) })]
TService,
TImplementation>();
Non-goals
- no changes to the C# type system
- no runtime validation
- no replacement for native generic constraints
The solution is intentionally based on static analysis only.
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net5.0 was computed. net5.0-windows was computed. net6.0 was computed. net6.0-android was computed. net6.0-ios was computed. net6.0-maccatalyst was computed. net6.0-macos was computed. net6.0-tvos was computed. net6.0-windows was computed. net7.0 was computed. net7.0-android was computed. net7.0-ios was computed. net7.0-maccatalyst was computed. net7.0-macos was computed. net7.0-tvos was computed. net7.0-windows was computed. net8.0 was computed. net8.0-android was computed. net8.0-browser was computed. net8.0-ios was computed. net8.0-maccatalyst was computed. net8.0-macos was computed. net8.0-tvos was computed. net8.0-windows was computed. net9.0 was computed. net9.0-android was computed. net9.0-browser was computed. net9.0-ios was computed. net9.0-maccatalyst was computed. net9.0-macos was computed. net9.0-tvos was computed. net9.0-windows was computed. net10.0 was computed. net10.0-android was computed. net10.0-browser was computed. net10.0-ios was computed. net10.0-maccatalyst was computed. net10.0-macos was computed. net10.0-tvos was computed. net10.0-windows was computed. |
| .NET Core | netcoreapp2.0 was computed. netcoreapp2.1 was computed. netcoreapp2.2 was computed. netcoreapp3.0 was computed. netcoreapp3.1 was computed. |
| .NET Standard | netstandard2.0 is compatible. netstandard2.1 was computed. |
| .NET Framework | net461 was computed. net462 was computed. net463 was computed. net47 was computed. net471 was computed. net472 was computed. net48 was computed. net481 was computed. |
| MonoAndroid | monoandroid was computed. |
| MonoMac | monomac was computed. |
| MonoTouch | monotouch was computed. |
| Tizen | tizen40 was computed. tizen60 was computed. |
| Xamarin.iOS | xamarinios was computed. |
| Xamarin.Mac | xamarinmac was computed. |
| Xamarin.TVOS | xamarintvos was computed. |
| Xamarin.WatchOS | xamarinwatchos was computed. |
-
.NETStandard 2.0
- No dependencies.
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories
This package is not used by any popular GitHub repositories.