Support for ```required``` properties
See original GitHub issueProblem Statement
Traditionally, Autofac creates objects by calling one of their constructors. The constructor accepts dependencies and then assigns/initializes values.
Starting in C#11, dependencies can also be expressed using the required
keyword. When a property is required
, if the constructor that was called does not have the [SetsRequiredMembers]
attribute, the property must have a value set immediately following construction.
Currently AutoFac does not support this core enhancement to object construction.
Desired Solution
When Autofac constructs an object, the constructor should be examined for [SetsRequiredMembers]
. If it is not found, all writable properties containing the RequiredMemberAttribute
attribute should be injected.
public class Foo1 {
//This should be injected
public required Dependency? Dep { protected get; init; }
}
public class Foo2 {
//This should not
public required Dependency? Dep { protected get; init; }
[SetsRequiredMembers]
public Foo2() {
this.Dep = null;
}
}
Additional Context
Because C#11 introduces this core-level enhancement to object construction, the above rules should always be enabled.
The following code will be helpful in implementing this enhancement:
public class PS : IPropertySelector {
public static IPropertySelector Instance { get; }
private static string RequiredAttributeName { get; }
private static string SetsRequiredMembersAttributeName { get; }
static PS() {
Instance = new PS();
//The type names are stored as strings so that this can also be used with legacy .NET platforms
RequiredAttributeName = "System.Runtime.CompilerServices.RequiredMemberAttribute";
SetsRequiredMembersAttributeName = "System.Diagnostics.CodeAnalysis.SetsRequiredMembersAttribute";
}
public bool NeedsPropertyInjection(ConstructorInfo constructorInfo) {
var SetsRequiredMembers = constructorInfo.GetCustomAttributesData().Any(x => string.Equals(x.AttributeType.FullName, SetsRequiredMembersAttributeName, StringComparison.InvariantCultureIgnoreCase));
var ret = !SetsRequiredMembers;
return ret;
}
public bool InjectProperty(PropertyInfo propertyInfo, object instance) {
var ret = propertyInfo.CanWrite
&& propertyInfo.GetCustomAttributesData().Any(x => string.Equals(x.AttributeType.FullName, RequiredAttributeName, StringComparison.InvariantCultureIgnoreCase))
;
return ret;
}
}
Issue Analytics
- State:
- Created 10 months ago
- Reactions:1
- Comments:25 (13 by maintainers)
Top GitHub Comments
@TonyValenti, required properties shipped: https://github.com/autofac/Autofac/releases/tag/v7.0.0
I don’t think we need to be sold on the value of the feature. At this point it’s more a question of how it should work and how we can remain compatible with M.E.DI. I’m almost more concerned about that compatibility issue because trying to retrofit compatibility has caused us a lot of trouble in the past. Folks, for whatever reason, choose Autofac as the underlying container and then complain when it isn’t identical to the Microsoft container.