-
-
Notifications
You must be signed in to change notification settings - Fork 36
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Unity GetService for Struct Type with a default constructor calls the constructor #87
Comments
I am not sure, is this incorrect behavior? |
It is different behavior than what I would get if I would call var c1 = new ClassWithOptionalArgsCtorWithStructs();
Console.WriteLine(c1.StructWithConstructor.ConstructorInvoked); // prints "false"
var c2 = ActivatorUtilities.CreateInstance(unityServiceProvider, typeof(ClassWithOptionalArgsCtorWithStructs));
Console.WriteLine(c2.StructWithConstructor.ConstructorInvoked); // prints "true" |
Unity compiles pipeline as It is concerning that you are using |
I'm unit testing the behavior of |
I understand, the remark was just a general rant. If I understand correctly, the behavior is not wrong and there is nothing required on my part to change it? |
The behavior using a Unity ServiceProvider is different than all the other DI providers being tested in |
It would be rather hard to change. Unity creates pipeline like this: return new ClassWithOptionalArgsCtorWithStructs( new StructWithPublicDefaultConstructor() ); I am not sure how this could be replaced with Optional or not, the struct is still allocated on the stack, so it is required to be initialized, what am I missing? |
The reason Unity's behavior is different in public object CreateInstance(IServiceProvider provider)
{
for (int index = 0; index != _parameters.Length; index++)
{
if (_parameterValues[index] == null)
{
object? value = provider.GetService(_parameters[index].ParameterType);
if (value == null)
{
if (!ParameterDefaultValue.TryGetDefaultValue(_parameters[index], out object? defaultValue))
Check out dotnet/csharplang#99 for more info. But when you have a Struct Type that defines a parameterless constructor, the following lines of code do different things: StructWithPublicDefaultConstructor c1 = default;
StructWithPublicDefaultConstructor c2 = new StructWithPublicDefaultConstructor();
|
By original design Unity attempts to create an instance even if it is not registered. It does not care if it is a class or struct as long as it could be instantiated. I will do some research but I am afraid this 'feature' can not be changed. A type (event struct) could be annotated with attributes for initialization: fields, properties, methods and can not be created with Unity already allows most of these, just with DefaultValue and other attributes: Allow no-arg constructor and field initializers... |
I'm adding a test for dotnet/runtime#47722. In doing so, I created a Struct type that has a default constructor (note you can only do this in IL today, until dotnet/csharplang#99 is implemented).
Calling
ActivatorUtilities.CreateInstance(provider, typeof(ClassWithOptionalArgsCtorWithStructs))
for a class whose constructor is defined like the following:Fails the following test:
The constructor shouldn't have been invoked because I didn't register
StructWithPublicDefaultConstructor
as a service. However, debugging into it, the Unit ServiceProvider is finding the ConstructorInfo on the ValueType and invoking it.Unity is the only DI provider with this behavior. The other providers return
null
for this Type, and the test passes.I needed to special case Unity's behavior in this test. So I logged an issue to ensure this is the behavior we are expecting for Unity.
The text was updated successfully, but these errors were encountered: