Coder Social home page Coder Social logo

extraconstraints's Introduction

ExtraConstraints.Fody

Chat on Gitter NuGet Status

Facilitates adding constraints for Enum and Delegate to types and methods.

See Milestones for release notes.

This is an add-in for Fody

It is expected that all developers using Fody become a Patron on OpenCollective. See Licensing/Patron FAQ for more information.

Usage

See also Fody usage.

NuGet installation

Install the ExtraConstraints.Fody NuGet package and update the Fody NuGet package:

PM> Install-Package Fody
PM> Install-Package ExtraConstraints.Fody

The Install-Package Fody is required since NuGet always defaults to the oldest, and most buggy, version of any dependency.

Add to FodyWeavers.xml

Add <ExtraConstraints/> to FodyWeavers.xml

<Weavers>
  <ExtraConstraints/>
</Weavers>

Your Code

public class Sample
{
    public void MethodWithDelegateConstraint<[DelegateConstraint] T> () {...}

    public void MethodWithTypeDelegateConstraint<[DelegateConstraint(typeof(Func<int>))] T> () {...}

    public void MethodWithEnumConstraint<[EnumConstraint] T>() {...}

    public void MethodWithTypeEnumConstraint<[EnumConstraint(typeof(ConsoleColor))] T>() {...}
}

What gets compiled

public class Sample
{
    public void MethodWithDelegateConstraint<T>() where T: Delegate {...}

    public void MethodWithTypeDelegateConstraint<T>() where T: Func<int> {...}

    public void MethodWithEnumConstraint<T>() where T: struct, Enum {...}

    public void MethodWithTypeEnumConstraint<T>() where T: struct, ConsoleColor {...}
}

Credit

Inspired by Jon Skeets blog post Generic constraints for enums and delegates.

Based mainly on code from Jb Evain's blog post Constraining generic constraints.

Icon

Straightjacket designed by Luis Prado from The Noun Project.

extraconstraints's People

Contributors

dependabot-preview[bot] avatar dependabot-support avatar dependabot[bot] avatar dracool avatar erikeckhardt avatar simoncropp avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar

extraconstraints's Issues

How to use it

In lieu of wiki, would be good to showcase usage with the following sample:

public class Sample
{
    public void MethodWithDelegateConstraint<[DelegateConstraint] T> ()
    {        
    }
    public void MethodWithEnumConstraint<[EnumConstraint] T>()
    {
    }
    public void MethodWithASpecificEnumConstraint<[EnumConstraint(typeof(SomeEnum))] T>()
    {
    }
} 

Where option # 3 highlights how to constraint to a specific enum

Referenced Projects

This is a really great and elegant solution to provide these constraints for a single project. However it really breaks down when you want to spread your code over multiple projects.

If you define a generic type or interface in one assembly with an EnumConstraint and then want to implement the interface or extend the base class in another assembly you will get errors.

The crux of the issue is this: you have to do all of the IL weaving after all the assemblies have successfully compiled. If you replace the constraints in each assembly as they are compiled, as it is now setup to do, you'll end up trying to compile constrained code in a dependent project against an unconstrained reference assembly, and that will fail.

NugetPackage: .NET 3.5 compatibility

The current package will not install into a project targeting .NET 3.5.

Fody itself will happily install into those project. Either both ExtraConstraints & Fody should work or neither.

Add `struct` constraint to `[EnumConstraint]` by default

Enum is an ungodly special type and I could go on and on about the deficiencies and shortcomings of its design that would be ridiculously easy to fix in a point update to the language, but I won't.

However, in order to use Enum.TryParse<T>, T must be non-nullable. The easiest way to get a non-nullable constraint (and it would be fully compatible with [EnumConstraint]) is to simply specify an additional where T: struct constraint. Since all enums in C# are non-nullable types (aka "structs"), Foo<[EnumConstraint] T> should automatically also constrain T to struct as well.

Doesn't work correctly with iterator methods

It appears that miking the enum constraint (and I would assume the delegate constraint) with C# iterator methods doesn't work. Here is a unit test that reproduces the issue:

public enum MyEnum
{
    None = 0,
    Value = 1,
}

public class MyClass<[EnumConstraint] T> where T : struct
{
}

public class MyFactory<[EnumConstraint] T> where T : struct
{
    public IEnumerable<MyClass<T>> Create()
    {
        yield return new MyClass<T>();
    }
}

[TestFixture]
public class ExtraConstraintsTests
{
    [Test]
    public void MyTest()
    {
        var factory = new MyFactory<MyEnum>();
        var enumerable = factory.Create();
    }
}

This gives a runtime error of: "System.TypeLoadException : GenericArguments[0], 'T', on 'MyClass1[T]' violates the constraint of type parameter 'T'." on the call tofactory.Create()`. (note, the behavior is somewhat easier to see if the classes are in a different assembly than the unit test because that delays the type load).

From looking at the disassembly with ilspy, I am thinking the problem is that the enum constraint is not applied to the iterator class that is automatically generated by the compiler.

Cannot Apply to Interfaces

I wanted to write this interface:

public interface IRandomProvider
{
    // snip

    /// <summary>
    /// Gets a random value defined on an enum type.
    /// </summary>
    /// <typeparam name="T">
    /// The <see cref="Enum"/> type that defines the random values we can get.
    /// </typeparam>
    /// <returns>
    /// A random value defined on <typeparamref name="T"/>.
    /// </returns>
    T Next<[EnumConstraint] T>();

    // snip
}

but this weaver only checks classes.

This should also check interfaces as well.

Type-specific EnumConstraintAttribute

If EnumConstraintAttribute took a Type constructor parameter (note that this would have to be a constant expression according to the C# spec - so it would be a typeof expression or a constant representing one - so it would be impossible to make this ambiguous) Fody could constrain that generic parameter to that specific enum instead of just System.Enum, correct?

This would help immensely with type safety if possible. Thanks for this awesome library and the easy to use packages.

Build proceeds when constraint is violatied.

Thanks for the strong name fix. I've installed it and could build the project. But it does not work for me, or I'm doing something wrong. For instance, in this extension method:

   public static TEnum ToEnum<[EnumConstraint] TEnum>(this string value)
    {
        return (TEnum) Enum.Parse(typeof (TEnum), value);
    }

I can pass any non-Enum type as a generic argument and the project builds successfully (namely some class type). Isn't the build supposed to be stopped if constraint is violated?

Can't Compile When Signing

I get an error when I try to compile this with a pfx file:

'''
Error 2 Fody: An unhandled exception occurred:

Exception:
Unable to obtain public key for StrongNameKeyPair.

StackTrace:
at System.Reflection.StrongNameKeyPair.ComputePublicKey()
at System.Reflection.StrongNameKeyPair.get_PublicKey()
at Mono.Cecil.ModuleWriter.WriteModuleTo(ModuleDefinition module, Stream stream, WriterParameters parameters) in c:\Code\cecil\Mono.Cecil\AssemblyWriter.cs:line 100
at Mono.Cecil.ModuleDefinition.Write(Stream stream, WriterParameters parameters) in c:\Code\cecil\Mono.Cecil\ModuleDefinition.cs:line 933
at Mono.Cecil.ModuleDefinition.Write(String fileName, WriterParameters parameters) in c:\Code\cecil\Mono.Cecil\ModuleDefinition.cs:line 922
at InnerWeaver.WriteModule() in c:\Code\Fody\FodyIsolated\ModuleWriter.cs:line 20
at InnerWeaver.Execute() in c:\Code\Fody\FodyIsolated\InnerWeaver.cs:line 34

Source:
mscorlib

TargetSite:
Byte[] ComputePublicKey()
ExtraConstraints
'''

I've never got an exception dump in the error list before so I don't really know where to go from here.

'ExtraConstraints' does not have a strong name.

Using 1.10.2.0 version. Get this error during compilation:

error CS1577: Assembly generation failed -- Referenced assembly 'ExtraConstraints' does not have a strong name

Would be lovely to make it work out of the box.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.