AutoConstructor 3.0.0
See the version list below for details.
dotnet add package AutoConstructor --version 3.0.0
NuGet\Install-Package AutoConstructor -Version 3.0.0
<PackageReference Include="AutoConstructor" Version="3.0.0"> <PrivateAssets>all</PrivateAssets> <IncludeAssets>runtime; build; native; contentfiles; analyzers</IncludeAssets> </PackageReference>
paket add AutoConstructor --version 3.0.0
#r "nuget: AutoConstructor, 3.0.0"
// Install AutoConstructor as a Cake Addin #addin nuget:?package=AutoConstructor&version=3.0.0 // Install AutoConstructor as a Cake Tool #tool nuget:?package=AutoConstructor&version=3.0.0
AutoConstructor
C# source generator that generates a constructor from readonly fields in a class.
Installation
- Grab the latest package on NuGet.
Requirements
Version | Visual Studio | .NET SDK |
---|---|---|
⇐1.3.0 | 16.10+ | 5.0.300+ |
>=2.0.0 | 17.0+ | 6.0.100+ |
Basic usage
The following code:
[AutoConstructor]
public partial class MyClass
{
private readonly MyDbContext _context;
private readonly IHttpClientFactory _clientFactory;
private readonly IService _service;
[AutoConstructorInject("options?.Value", "options", typeof(IOptions<ApplicationOptions>))]
private readonly ApplicationOptions _options;
}
will generate:
partial class MyClass
{
public MyClass(
MyApp.MyDbContext context,
System.Net.Http.IHttpClientFactory clientFactory,
MyApp.IService service,
Microsoft.Extensions.Options.IOptions<MyApp.ApplicationOptions> options)
{
this._context = context;
this._clientFactory = clientFactory;
this._service = service;
this._options = options?.Value;
}
}
A sample containing more cases is available at the end of this README.
How to use
For any class where the generator will be used:
- Mark the class as
partial
- Use
AutoConstructorAttribute
on the class
By default, all readonly
non-static
fields without initialization will be used. They will be injected with the same name without any leading _
.
Fields marked with AutoConstructorIgnoreAttribute
will be ignored.
Use AutoConstructorInjectAttribute
to customize the behavior, usualy when the injected parameter and the fields
do not have the same type. It takes three optionals parameters:
initializer
: a string that will be used to initialize the field (by examplemyService.GetData()
), default to theparameterName
if null or empty.parameterName
: the name of the parameter to used in the constructor (by examplemyService
), default to the field name trimmed if null or empty.injectedType
: the type of the parameter to used in the constructor (by exampleIMyService
), default to the field type if null.
If no parameters are provided, the behavior will be the same as without the attribute. Using the attribute on a field that would not be injected otherwise won't make the field injectable.
When using AutoConstructorInjectAttribute
, the parameter name can be shared across multiple fields,
and even use a parameter from another field not annotated with AutoConstructorInjectAttribute
, but type must match.
Get-only properties
Get-only properties (public int Property { get; }
) are injected by the generator by default.
The behavior of the injection can be modified using auto-implemented property field-targeted attributes on its backing field. The following code show an injected get-only property with a custom injecter:
[field: AutoConstructorInject(initializer: "injected.ToString()", injectedType: typeof(int), parameterName: "injected")]
public int Property { get; }
⚠️ The compiler support for auto-implemented property field-targeted attributes is not perfect (as described in the link above), and Roslyn analyzers are not running on backings fields so some warnings may not be reported.
Configuration
Generating ArgumentNullException
By default, null checks with ArgumentNullException
are not generated when needed.
To enable this behavior, set AutoConstructor_DisableNullChecking
to false
in the project file:
<AutoConstructor_DisableNullChecking>false</AutoConstructor_DisableNullChecking>
Generating XML documentation comment
By default, no XML documentation comment will be generated for the constructor.
To enable this behavior, set AutoConstructor_GenerateConstructorDocumentation
to true
in the project file:
<AutoConstructor_GenerateConstructorDocumentation>true</AutoConstructor_GenerateConstructorDocumentation>
This will generate a default comment like this one, with each parameter reusing the corresponding field summary if available, and the parameter name otherwise:
/// <summary>
/// Initializes a new instance of the Test class.
/// </summary>
/// <param name=""t1"">Some field.</param>
/// <param name=""t2"">t2</param>
By using the AutoConstructor_ConstructorDocumentationComment
property, you can configure the comment message:
<AutoConstructor_ConstructorDocumentationComment>Some comment for the {0} class.</AutoConstructor_ConstructorDocumentationComment>
This will generate the following code:
/// <summary>
/// Some comment for the Test class.
/// </summary>
/// <param name=""t1"">Some field.</param>
/// <param name=""t2"">t2</param>
Samples describing some cases
Sample for fields
The following code
[AutoConstructor]
partial class Test
{
private readonly string _name;
// Won't be injected
private readonly Uri _uri = new Uri("/non-modified", UriKind.Relative);
// Won't be injected
[AutoConstructorIgnore]
private readonly DateTime _dateNotTaken;
// Won't be injected
private int? _toto;
// Support for nullables
private readonly DateTime? _date;
// Support for generics
private readonly List<DateTime> _items;
// Inject with custom initializer
[AutoConstructorInject("guid.ToString()", "guid", typeof(Guid))]
private readonly string _guidString;
// Use existing parameter defined with AutoConstructorInject
[AutoConstructorInject("guid.ToString().Length", "guid", typeof(Guid))]
private readonly int _guidLength;
// Use existing parameter from a basic injection
[AutoConstructorInject("name.ToUpper()", "name", typeof(string))]
private readonly string _nameShared;
}
will generate
public Test(string name, System.DateTime? date, System.Collections.Generic.List<System.DateTime> items, System.Guid guid)
{
this._name = name ?? throw new System.ArgumentNullException(nameof(name));
this._date = date ?? throw new System.ArgumentNullException(nameof(date));
this._items = items ?? throw new System.ArgumentNullException(nameof(items));
this._guidString = guid.ToString() ?? throw new System.ArgumentNullException(nameof(guid));
this._guidLength = guid.ToString().Length;
this._nameShared = name.ToUpper() ?? throw new System.ArgumentNullException(nameof(name));
}
Sample for get-only properties
The following code
[AutoConstructor]
public partial class Test
{
[field: AutoConstructorInject]
public int Injected { get; }
public int AlsoInjectedEvenWhenMissingAttribute { get; }
/// <summary>
/// Some property.
/// </summary>
[field: AutoConstructorInject]
public int InjectedWithDocumentation { get; }
[field: AutoConstructorInject]
public int NotInjectedBecauseNotReadonly { get; set; }
[field: AutoConstructorInject]
public static int NotInjectedBecauseStatic { get; }
[field: AutoConstructorInject]
public int NotInjectedBecauseInitialized { get; } = 2;
[field: AutoConstructorIgnore]
public int NotInjectedBecauseHasIgnoreAttribute { get; }
[field: AutoConstructorInject(initializer: ""injected.ToString()"", injectedType: typeof(int), parameterName: ""injected"")]
public string InjectedWithoutCreatingAParam { get; }
}
will generate
partial class Test
{
/// <summary>
/// Initializes a new instance of the Test class.
/// </summary>
/// <param name=""injected"">injected</param>
/// <param name=""injectedWithDocumentation"">Some property.</param>
/// <param name=""alsoInjectedEvenWhenMissingAttribute"">alsoInjectedEvenWhenMissingAttribute</param>
public Test(int injected, int injectedWithDocumentation, int alsoInjectedEvenWhenMissingAttribute)
{
this.Injected = injected;
this.InjectedWithDocumentation = injectedWithDocumentation;
this.AlsoInjectedEvenWhenMissingAttribute = alsoInjectedEvenWhenMissingAttribute;
this.InjectedWithoutCreatingAParam = injected.ToString() ?? throw new System.ArgumentNullException(nameof(injected));
}
}
Diagnostics
ACONS01
The AutoConstructor
attribute is used on a class that is not partial.
ACONS02
The AutoConstructor
attribute is used on a class without fields to inject.
ACONS03
The AutoConstructorIgnore
attribute is used on a field that won't already be processed.
ACONS04
The AutoConstructorInject
attribute is used on a field that won't already be processed.
ACONS05
The AutoConstructorIgnore
or AutoConstructorInject
are used on a class without the AutoConstructor
attribute.
ACONS06
A type specified in AutoConstructorInject
attribute does not match the type of another parameter with the same name.
In the folowing sample, both fields will be injected with guid
as parameter name, but one of type string
and the other of type Guid
,
preventing the generator from running.
public partial class Test
{
[AutoConstructorInject("guid.ToString()", "guid", typeof(Guid))]
private readonly string _guid2;
private readonly string _guid;
}
Learn more about Target Frameworks and .NET Standard.
This package has no dependencies.
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories (1)
Showing the top 1 popular GitHub repositories that depend on AutoConstructor:
Repository | Stars |
---|---|
Sergio0694/ComputeSharp
A .NET library to run C# code in parallel on the GPU through DX12, D2D1, and dynamically generated HLSL compute and pixel shaders, with the goal of making GPU computing easy to use for all .NET developers! 🚀
|
Version | Downloads | Last updated |
---|---|---|
5.6.0 | 1,565 | 9/22/2024 |
5.5.0 | 4,460 | 6/26/2024 |
5.5.0-beta.1 | 52 | 6/24/2024 |
5.4.1 | 474 | 6/22/2024 |
5.4.0 | 3,864 | 5/23/2024 |
5.3.0 | 5,237 | 3/16/2024 |
5.3.0-beta.2 | 61 | 3/15/2024 |
5.3.0-beta.1 | 92 | 3/12/2024 |
5.2.1 | 11,684 | 3/4/2024 |
5.2.0 | 4,692 | 12/19/2023 |
5.1.0 | 7,345 | 11/23/2023 |
5.0.1 | 258 | 11/22/2023 |
5.0.0 | 6,148 | 11/7/2023 |
5.0.0-beta.2 | 74 | 11/6/2023 |
5.0.0-beta.1 | 89 | 11/2/2023 |
4.1.1 | 8,605 | 7/18/2023 |
4.1.0 | 3,488 | 7/8/2023 |
4.0.3 | 7,158 | 4/24/2023 |
4.0.2 | 2,539 | 4/19/2023 |
4.0.1 | 1,583 | 3/29/2023 |
4.0.0 | 345 | 3/27/2023 |
3.2.5 | 5,572 | 10/15/2022 |
3.2.4 | 372 | 10/7/2022 |
3.2.3 | 685 | 6/28/2022 |
3.2.2 | 433 | 6/27/2022 |
3.2.1 | 459 | 6/11/2022 |
3.2.0 | 447 | 5/20/2022 |
3.1.1 | 445 | 5/14/2022 |
3.0.0 | 447 | 4/1/2022 |
3.0.0-beta.2 | 144 | 3/9/2022 |
3.0.0-beta.1 | 989 | 2/9/2022 |
2.3.0 | 520 | 1/27/2022 |
2.2.0 | 445 | 1/22/2022 |
2.1.0 | 430 | 1/21/2022 |
2.0.2 | 335 | 11/11/2021 |
1.3.0 | 445 | 9/21/2021 |
1.2.1 | 347 | 8/28/2021 |
1.2.0 | 347 | 8/28/2021 |
1.1.0 | 336 | 8/26/2021 |
1.0.2 | 418 | 8/2/2021 |
1.0.1 | 468 | 7/24/2021 |
1.0.0 | 415 | 7/23/2021 |