OpenGenericConstraints.Abstractions
0.1.0
AdvancedGenericTypeConstraints.Abstractions
Additional DetailsWas renamed to AdvancedGenericTypeConstraints.Abstractions
dotnet add package OpenGenericConstraints.Abstractions --version 0.1.0
NuGet\Install-Package OpenGenericConstraints.Abstractions -Version 0.1.0
<PackageReference Include="OpenGenericConstraints.Abstractions" Version="0.1.0" />
<PackageVersion Include="OpenGenericConstraints.Abstractions" Version="0.1.0" />
<PackageReference Include="OpenGenericConstraints.Abstractions" />
paket add OpenGenericConstraints.Abstractions --version 0.1.0
#r "nuget: OpenGenericConstraints.Abstractions, 0.1.0"
#:package OpenGenericConstraints.Abstractions@0.1.0
#addin nuget:?package=OpenGenericConstraints.Abstractions&version=0.1.0
#tool nuget:?package=OpenGenericConstraints.Abstractions&version=0.1.0
OpenGenericConstraints
OpenGenericConstraints enables compile-time-like validation for open generic constraints in C# by combining lightweight attributes with a Roslyn analyzer.
Why this exists
C# generic constraints cannot express rules like "the supplied type must implement IHandleMessages<T> for some T"
when the constraint targets an open generic type definition.
This project closes that gap with:
- a small abstractions package that exposes constraint attributes
- a Roslyn analyzer package that validates the supplied type arguments at compile time
Packages
Install both packages in the consuming project:
<ItemGroup>
<PackageReference Include="OpenGenericConstraints.Abstractions" Version="0.1.0" />
<PackageReference Include="OpenGenericConstraints.Analyzers" Version="0.1.0" PrivateAssets="all" />
</ItemGroup>
Example
using OpenGenericConstraints;
public interface IHandleMessages<TMessage>;
public interface IFeatureRegistry
{
void RegisterMessageHandler<
[MustImplementOpenGeneric(typeof(IHandleMessages<>))] TMessageHandler>();
}
public sealed class MyMessage;
public sealed class MyHandler : IHandleMessages<MyMessage>;
Using RegisterMessageHandler<MyHandler>() is valid.
Using a type that does not match the configured open generic definition produces:
OGC001: Type 'MyHandler' must implement 'IHandleMessages<>'
Matching semantics
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
This means matching is not limited to interfaces. Open generic classes, interfaces, and other generic type definitions are all supported as long as the open generic definition matches.
Current API
The project currently supports:
MustImplementOpenGenericAttributeMustImplementOpenGenericAttribute(Type openGenericType, bool exactlyOne)MustNotImplementOpenGenericAttribute
Example:
public interface IFeatureRegistry
{
void RegisterSingle<
[MustImplementOpenGeneric(typeof(IHandleMessages<>), true)]
THandler>();
void RegisterWithoutSagaStarter<
[MustNotImplementOpenGeneric(typeof(IAmStartedByMessages<>))]
THandler>();
}
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.
| Version | Downloads | Last Updated | |
|---|---|---|---|
| 0.1.0 | 153 | 4/2/2026 |