dadhi / DryIoc

DryIoc is fast, small, full-featured IoC Container for .NET
MIT License
1.02k stars 123 forks source link

Func<> with arguments #666

Open Griboedoff opened 4 days ago

Griboedoff commented 4 days ago

net6, DryIoc 5.4.3

Hi!

I can't find the way to reuse depencency A when using creation Func for B.

My use case is this:

currently DryIoc calls A constructor every time getB called.

Is there a way to reuse A instance in creating B?

P.S. I saw docs for Func wrapper but asResolutionCall does not do the job.

using DryIoc;

var dc = new Container(
    r => r
        .WithMicrosoftDependencyInjectionRules()
        .WithDefaultIfAlreadyRegistered(IfAlreadyRegistered.Throw)
        .WithConcreteTypeDynamicRegistrations()
        .WithIgnoringReuseForFuncWithArgs());
dc.Register<A>(reuse: Reuse.Singleton);
dc.Register<B>();
var getB = dc.Resolve<Func<string, B>>();
getB("1");
getB("2");

class A
{
    public A()
        => Console.WriteLine("A created");
}

class B
{
    public B(A a, string s) {}
}
dadhi commented 3 days ago

@Griboedoff Does it work if you remove .WithIgnoringReuseForFuncWithArgs()?

Griboedoff commented 3 days ago

It will.

But for some legacy reasons we have .WithDefaultReuse(Reuse.Singleton) on whole container Is there any way to achieve same behaviour?

dadhi commented 3 days ago

I need to think about that. Problem is, I cannot say if a scoped service or singleton or its dependency still need the passed argument. Container can tell that for sure only when traversing to the last dependency in a chain. By this moment, it is already too late to keep the reuse. Another approach may be to mark a specific dependency with reuse to be omitted by this rule. More configs to the God of configs :)

Griboedoff commented 3 days ago

Okay, thanks

For now I think the best solution is explicit factory for class B which curries all arguments except string from B constructor

dadhi commented 3 days ago

But let keep this issue open for now. It is also an interesting number of issue.