JinShil.MixinSourceGenerator by Jin Shil
NuGet / site data
Details
Info
Name: JinShil.MixinSourceGenerator
A C# source generator for composing classes or structs from other classes or structs using mixins.
Author: Jin Shil
NuGet: https://www.nuget.org/packages/JinShil.MixinSourceGenerator/
You can find more details at https://github.com/JinShil/JinShil.MixinSourceGenerator
Source: https://github.com/JinShil/JinShil.MixinSourceGenerator
Author
Jin Shil
Original Readme
JinShil.MixinSourceGenerator
This is a very simple, but powerful C# source generator that simplifies class and struct composition through the use of mixins.
It dramatically increases code reuse by copying members, including attributes and XML comments, verbatim from one or more implementation types to another type. The resulting type becomes a composition of the implementation types without employing inheritance, extensions, default interface methods, or any other specialized language feature.
It simply copies and pastes members from one or more types into another.
Example
The following example demonstrates how to use this source generator to compose a class from two implementation classes.
- Apply one or more
[Mixin(typeof(TypeToMixIn))]
attributes to a partial class or struct, specifying the types to mix in. - The source generator scans for the specified types and copies their members, including attributes and XML comments, verbatim into the attributed type.
Source Code
internal class Implementation1
{
/// <summary>
/// Summary for Property1
/// </summary>
[SomeAttribute]
public int Property1 \{ get; }
/// <summary>
/// Summary for Method1
/// </summary>
[SomeAttribute]
public void Method1()
{
Console.WriteLine("Running Method 1");
}
}
internal class Implementation2
{
/// <summary>
/// Summary for Property2
/// </summary>
[SomeAttribute]
public int Property2 \{ get; }
/// <summary>
/// Summary for Method2
/// </summary>
[SomeAttribute]
public void Method2()
{
Console.WriteLine("Running Method 2");
}
}
[Mixin(typeof(Implementation1))]
[Mixin(typeof(Implementation2))]
public partial class Composition : SomeBaseClass, ISomeInterface
{
}
Generated Code
The above code will result in the following generated code, a composition of Implementation1
and Implementation2
.
[Mixin(typeof(Implementation1))]
[Mixin(typeof(Implementation2))]
public partial class Composition : SomeBaseClass, ISomeInterface
{
/// <summary>
/// Summary for Property1
/// </summary>
[SomeAttribute]
public int Property1 \{ get; }
/// <summary>
/// Summary for Method1
/// </summary>
[SomeAttribute]
public void Method1()
{
Console.WriteLine("Running Method 1");
}
/// <summary>
/// Summary for Property2
/// </summary>
[SomeAttribute]
public int Property2 \{ get; }
/// <summary>
/// Summary for Method2
/// </summary>
[SomeAttribute]
public void Method2()
{
Console.WriteLine("Running Method 2");
}
}
The [MixinIgnore]
Attribute
The [MixinIgnore]
attribute can be added to implementation type members, allowing the implementation type to compile, but deferring the member's implementation to the composed type.
Source Code
internal class Implementation
{
// The source generator will not copy this method into any composition type.
// This member is effectively just a stub, so that this implementation class will compile.
[MixinIgnore]
void Method1()
\{ }
/// <summary>
/// Summary of Method2
/// </summary>
public void Method2()
{
Method1();
}
}
[Mixin(typeof(Implementation))]
public partial class Composition
{
/// <summary>
/// Summary of Method1
/// </summary>
public void Method1()
{
Console.WriteLine("Running Method1");
}
}
Generated Code
The above code will result in the following generated code. Implementation.Method2()
will call Composition.Method1()
, not Implementation.Method1()
.
public partial class Composition
{
/// <summary>
/// Summary of Method1
/// </summary>
public void Method1()
{
Console.WriteLine("Running Method1");
}
/// <summary>
/// Summary of Method2
/// </summary>
public void Method2()
{
Method1();
}
}
License
This repository is licensed under the GNU General Public License (GPL). The GPL applies only to the source code in this repository. Code generated by the source generator is not subject to this license and can be used according to your own project's licensing terms.
About
Generate mixins of classes
How to use
Example (source csproj, source files)
- CSharp Project
- Program.cs
- Person.cs
- LogData.cs
This is the CSharp Project that references JinShil.MixinSourceGenerator
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net8.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>
<PropertyGroup>
<EmitCompilerGeneratedFiles>true</EmitCompilerGeneratedFiles>
<CompilerGeneratedFilesOutputPath>$(BaseIntermediateOutputPath)\GX</CompilerGeneratedFilesOutputPath>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="JinShil.MixinSourceGenerator" Version="1.0.0">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
</ItemGroup>
</Project>
This is the use of JinShil.MixinSourceGenerator in Program.cs
using DemoMixin;
Person person = new Person \{ Name = "Andrei Ignat" };
person.LogName();
This is the use of JinShil.MixinSourceGenerator in Person.cs
using JinShil.MixinSourceGenerator;
namespace DemoMixin;
[Mixin(typeof(LogData))]
partial class Person
{
public string Name \{ get; set; }=string.Empty;
public void LogName() => this.Log(Name);
}
This is the use of JinShil.MixinSourceGenerator in LogData.cs
namespace DemoMixin;
internal class LogData
{
public void Log(string data) => Console.WriteLine(data);
}
Generated Files
Those are taken from $(BaseIntermediateOutputPath)\GX
- MixinAttribute.g.cs
- MixinIgnoreAttribute.g.cs
- Person.g.cs
namespace JinShil.MixinSourceGenerator
{
/// <summary>
/// Specifies the type whose members are to be mixed in to a partial class or struct.
/// </summary>
[System.AttributeUsage(System.AttributeTargets.Class | System.AttributeTargets.Struct, AllowMultiple = true)]
public class MixinAttribute : System.Attribute
{
public System.Type Type \{ get; }
public MixinAttribute(System.Type type)
{
Type = type;
}
}
}
namespace JinShil.MixinSourceGenerator
{
/// <summary>
/// Used to identify a member that should be ignored when mixing in members from other types.
/// </summary>
[System.AttributeUsage(System.AttributeTargets.Method | System.AttributeTargets.Property | System.AttributeTargets.Field | System.AttributeTargets.Event, AllowMultiple = false)]
public class MixinIgnoreAttribute : System.Attribute
{
public MixinIgnoreAttribute()
\{ }
}
}
#nullable enable
namespace DemoMixin
{
partial class Person
{
public void Log(string data) => Console.WriteLine(data);
}
}
Useful
Download Example (.NET C#)
Share JinShil.MixinSourceGenerator
https://ignatandrei.github.io/RSCG_Examples/v2/docs/JinShil.MixinSourceGenerator
Category "Mixin" has the following generators:
1 JinShil.MixinSourceGenerator