LokiMidgard / PartialMixins

Extends C# with Mixins.
MIT License
24 stars 2 forks source link

NuGet Build status GitHub license

PartialMixins

Extends C# with Mixins. The Mixins are simulated using partial classes, instead of ilweaving like other librarys. The MixinAttribute copys all members of the targeted Mixin to a partial class implementation of the anotated type. This give you intellisense support on your classes. It uses the roslyn code generation framework.

Usage

First add the NuGet package to your Project.

To create a Mixin just declare a class.

    class IdMixin
    {
        public Guid Id { get; set; } = Guid.NewGuid();
    }

To apply the mixin you need to declare the MixinAttribute on the class that should implement the desired mixin. This class must also have the partial modifyer. Pass the Type of the Mixin in the attribute constructor. After the next time you build your source the mixin is implemented by your class.

    [Mixin(typeof(IdMixin))]
    partial class BusinessObject
    {
        public string Name { get; set; }
    }

    class Program
    {
        static void Main(string[] args)
        {
            var b1 = new BusinessObject() { Name = "Paul" };
            Console.WriteLine($"{b1.Id}:{b1.Name}");
        }

    }

Your mixins can also implement interfaces.

    interface Id : IEquatable<Id>
    {
        Guid Id { get; }
    }

    class IdMixin : Id
    {
        public Guid Id { get; set; } = Guid.NewGuid();

        public bool Equals(Id other) => Id.Equals(other.Id);

    }

If you use the Mixin Type itself, it will be substitueded with the consuming type.

    abstract class AddMixin
    {
        public abstract AddMixin Add(AddMixin other);
        public static AddMixin operator +(AddMixin a1, AddMixin a2)
        {
            return a1.Add(a2);
        }
    }

A Type that uses this Mixin may look like this:

namespace Sample
{
    [Mixin(typeof(AddMixin))]
    public partial struct MyNumber
    {
        public int Value { get; }
        public MyNumber(int value) => this.Value = value;
        public partial MyNumber Add(MyNumber other) => new MyNumber(this.Value + other.Value);
    }
}

// Generated Code...

namespace Sample
{
    public partial struct MyNumber
    {
        [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Mixin Task", "1.0.51.0")]
        public partial Sample.MyNumber Add(Sample.MyNumber other);
        [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Mixin Task", "1.0.51.0")]
        public static Sample.MyNumber operator +(Sample.MyNumber a1, Sample.MyNumber a2)
        {
            return a1.Add(a2);
        }
    }
}

As you can see absract methods are implemented as partial Methods. That way you can reqirer the consumer of your Mixin to provide specific functionallity.

Restrictions

Roadmap

Legal

This Software is licensed under MIT.

Used Assets

Icon Combine created by Paul Philippe Berthelon Bravo published under Public Domain.