VContainer icon indicating copy to clipboard operation
VContainer copied to clipboard

Support for Container.Instantiate<T>(parameters)

Open revolt3r opened this issue 3 years ago • 2 comments

I would like to be able to instantiate simple C# classes with all dependencies from the current scope injected automatically + some custom parameters. Right now I'm really missing something similar to PlaceholderFactory from Zenject.

Same as this: https://github.com/hadashiA/VContainer/issues/54

Unfortunately Container.Inject allows injecting only instances.

revolt3r avatar Aug 30 '21 08:08 revolt3r

@revolt3r Hello! I have managed to resolve instances with the following extension method:

public static class VContainerExtensions
    {
        public static T ResolveInstance<T>(this IObjectResolver resolver) =>
            (T)resolver.Resolve(new RegistrationBuilder(typeof(T), Lifetime.Transient).Build());
    }

My example code that uses this extension:

builder.Register<IInitializationStateMachine>(resolver => InitializationStateMachine.Builder
                    .Add(resolver.ResolveInstance<LoginState>())
                    .Add(resolver.ResolveInstance<LoadMainMenuState>())
                    .Build(),
                Lifetime.Scoped);

It works for me and I think you can change this code to support your custom parameters

dre0dru avatar Nov 25 '21 10:11 dre0dru

A small note to the answer above:

You can get access to all types except for the type you are in:


public class MyService
{
    public class MyService(Service s) { }
}

public class Service
{
    public Service(this IObjectResolver resolver) =>
        s.ResolveInstance<MyService>(); //error, the `Service` not yet registered, method injection not working too
}

Instead you should register this as a parameter:

public static T ResolveInstance<T, TParam>(this IObjectResolver resolver, TParam parameter)
{
    var registrationBuilder = new RegistrationBuilder(typeof(T), Lifetime.Transient);
    registrationBuilder.WithParameter(parameter);
    return (T)resolver.Resolve(registrationBuilder.Build());
}

public class Service
{
    public Service(this IObjectResolver resolver) =>
        s.ResolveInstance<MyService, Service>(this); 
}

YegorStepanov avatar May 05 '22 21:05 YegorStepanov

Up.

I've come from Zenject and have been using such feature a lot. Especially in conjunction with IInstatiator (instead of using DiContainer directly).

@hadashiA, is it hard to implement? Do we have some workaround for that (ideally, without heap allocations)?

Artein avatar Nov 17 '22 10:11 Artein

I have considered this issue several times. For me, the main goal of this project was to create the right constraints that would not allow DI to be abused. As a matter of fact, that's why I don't put this feature in. You can inject a container, register it with a lambda expression that receives the container, or write a factory using the lambda expression that receives the container.

I found VContainer's extensibility to be sufficient. I'm not going to implement it unless I come up with a more specific and useful use case.

hadashiA avatar Feb 12 '24 02:02 hadashiA