sourcedepend by Colin Wilmans
Nuget / site data
Details
Info
Name: sourcedepend
A source generator for C# that uses Roslyn (the C# compiler) to allow you to generate your constructor for injection during compile time.
Author: Colin Wilmans
NuGet: https://www.nuget.org/packages/sourcedepend/
You can find more details at https://github.com/crwsolutions/sourcedepend
Original Readme
Source Depend
A source generator for C# that uses Roslyn (the C# compiler) to help you with dependency injection (DI). It saves you from writing the constructor because this will be written for you (during compile time). Just tag the member with a [Dependency] attribute.
Version history
- v0.1. First implementation.
- v0.2. Complete rewrite from ISourceGenerator to IIncrementalGenerator, this should boost performance
- keep sealed and accessibility intact.
- v0.3. Complete Rewrite: reorganized the code.
- Allow one level of inheritance.
How to use it
Install it and add the attribute to the fields or properties you want be set in your constructor, like so:
public partial class ExampleService
{
[Dependency]
private readonly AnotherService anotherService;
[Dependency]
AnotherService Prop { get; }
}
Alternative assignment
It is also possible that the generated assignment is to an alternative property:
public partial class ExampleService
{
[Dependency(nameof(BindingContext))]
AnotherService ViewModel => BindingContext as AnotherService;
}
Inheritance
And it is possible to inherit from a base implementation that also uses the [Dependency] attribute:
internal partial class BaseExampleService
{
[Dependency]
private readonly IForBaseService _someBaseService;
}
internal partial class ExampleService : BaseExampleService
{
}
Add construction work
Because your constructor is highjacked, there are the alternative methods PreConstruct/PostConstruct to do your construction work:
public partial class ExampleService
{
[Dependency]
private readonly AnotherService anotherService;
///This method will be called before the generated assignments
partial void PreConstruct()
{
Initialize()
}
///This method will be called after the generated assignments
partial void PostConstruct() => anotherService.ConstructValue = "Hello from post-construct!";
}
These samples give the following combined generated code:
namespace ConsoleApp
{
public partial class ExampleService
{
public ExampleService(ConsoleApp.IAnotherService anotherService, ConsoleApp.AnotherService prop, ConsoleApp.AnotherService viewModel, ConsoleApp.IForBaseService someBaseService) : base(someBaseService)
{
PreConstruct();
this.anotherService = anotherService;
Prop = prop;
BindingContext = viewModel;
PostConstruct();
}
partial void PreConstruct();
partial void PostConstruct();
}
}
namespace ConsoleApp
{
/// <inheritdoc/>
internal partial class BaseExampleService
{
public BaseExampleService(ConsoleApp.IForBaseService someBaseService)
{
PreConstruct();
this._someBaseService = someBaseService;
PostConstruct();
}
partial void PreConstruct();
partial void PostConstruct();
}
}
Installing
The package is available on NuGet. To install from the command line:
dotnet add package sourcedepend
Or use the Package Manager in Visual Studio.
Contributing
The main supported IDE for development is Visual Studio 2019.
Questions, comments, bug reports, and pull requests are all welcome. Bug reports that include steps to reproduce (including code) are preferred. Even better, make them in the form of pull requests.
Maintainers/Core team
Contributors can be found at the contributors page on Github.
License
This software is open source, licensed under the MIT License. See LICENSE for details. Check out the terms of the license before you contribute, fork, copy or do anything with the code. If you decide to contribute you agree to grant copyright of all your contribution to this project and agree to mention clearly if do not agree to these terms. Your work will be licensed with the project at MIT, along the rest of the code.
About
Generating constructor for DI
How to use
Example ( source csproj, source files )
- CSharp Project
- Program.cs
- Person.cs
This is the CSharp Project that references sourcedepend
<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="SourceDepend" Version="0.3.0" />
</ItemGroup>
</Project>
This is the use of sourcedepend in Program.cs
using CtorDemo;
var p = new Person("Andrei", "Ignat");
Console.WriteLine(p.FullName());
This is the use of sourcedepend in Person.cs
namespace CtorDemo;
internal partial class Person
{
[Dependency]
public readonly string? FirstName;
[Dependency]
public readonly string? LastName;
public string FullName() => $"{FirstName} {LastName}";
partial void PostConstruct()
{
Console.WriteLine("Person constructed");
}
partial void PreConstruct()
{
Console.WriteLine("Person constructing");
}
}
Generated Files
Those are taken from $(BaseIntermediateOutputPath)\GX
- Dependency.Generated.g.cs
- Person_Dependency.g.cs
// <auto-generated />
/// <summary>
/// Injects this item in the constructor. This will also highjack your constructor, so if you have any construct business, use PreConstruct() or PostConstruct() methods.
/// </summary>
/// <remarks>
/// Make sure your class is partial.
/// </remarks>
[System.AttributeUsage(System.AttributeTargets.Field | System.AttributeTargets.Property, Inherited = false, AllowMultiple = false)]
[System.Diagnostics.Conditional("DependencyGenerator_DEBUG")]
internal sealed class DependencyAttribute : System.Attribute
{
internal DependencyAttribute(string alternativePropertyName = null) { }
}
// <auto-generated/>
#pragma warning disable
#nullable enable
namespace CtorDemo
{
/// <inheritdoc/>
internal partial class Person
{
public Person(string? FirstName, string? LastName)
{
PreConstruct();
this.FirstName = FirstName;
this.LastName = LastName;
PostConstruct();
}
partial void PreConstruct();
partial void PostConstruct();
}
}
Usefull
Download Example (.NET C# )
Share sourcedepend
https://ignatandrei.github.io/RSCG_Examples/v2/docs/sourcedepend