1

I'm using DryIoc in a WebApi project. The default reuse is set to Reuse.InWebRequest. In some cases I need to resolve new instances during a request. When using Reuse.InCurrentScope I can resolve new instances like so:

public class Foo : IFoo
{
    public Foo(IMyDependency dep, IContainer container){
        using (var scope = container.OpenScope()) {
            var newInstance = scope.Resolve<IMyDependency>();
            Assert.IsFalse(ReferenceEquals(dep, newInstance));
        }
    }
}

But when using Request.InWebRequest or Request.InThread (which are basically the same according to the documentation) no new instances are created, but already resolved instances are reused. I also tried to use IContainer.CreateFacade() but the result is the same.

I'm wondering if there is a way to force the creation of new instances (regardless of the specified reuse) without creating a new container from scratch.

Update for clarification

I cannot use Reuse.Transient, because I need the same instance during the request 99% of the time. I need a new instance only when abusing the container as a service locator.

jasper
  • 521
  • 4
  • 17

2 Answers2

2

You may register service twice, one with scoped and another one with transient reuse. For the transient one specify a serviceKey when registering, and use it in service locator to identify the transient service.

dadhi
  • 4,807
  • 19
  • 25
  • I was considering this but didn't have time to test it. Perhaps you could include this use case in your Reuse documentation? – AJ X. Aug 28 '17 at 19:45
  • Thanks, this works, at least to some extent. I wrote a little extension method that copies all registrations with a lifetime greater than transient and smaller than singleton but adds a service key. The only problem is, that resolving an `IEnumerabley` results duplicate instances, one for the default registration an one for the keyed one. Will see if I can work around it. – jasper Aug 29 '17 at 16:59
  • You can register a decorator for IEnumerable, to filter whatever services based on key: https://bitbucket.org/dadhi/dryioc/wiki/Decorators#markdown-header-decorator-of-wrapper – dadhi Aug 29 '17 at 18:19
1

From the documentation, Reuse.Transient should achieve what you are looking for.

container.Register<IFoo, Foo>(Reuse.Transient);
AJ X.
  • 2,729
  • 1
  • 23
  • 33
  • True, but that doesn't work for me here because I need the same instance 99% of the time. Clarified my question. – jasper Aug 25 '17 at 15:49
  • It looks like there may be a way to create your own Reuse implementation. (see `IReuse`). You could use that to pass in a flag to indicate you need a new instance. – AJ X. Aug 25 '17 at 15:57
  • In DryIoc v2.* you need to implement both IReuse, IReuseV3. IReuse is the obsolete one, so NotImplementedException will be fine. Here is the example of [custom reuse](https://bitbucket.org/dadhi/dryioc/src/f10182d271cfd9463c1599ea37e4c77ad685ae61/Net45/DryIoc.IssuesTests/Issue169_FalseAlarmCheckingScopeLifetimeConsistencyForFuncWrapper.cs?at=default&fileviewer=file-view-default#Issue169_FalseAlarmCheckingScopeLifetimeConsistencyForFuncWrapper.cs-42) – dadhi Aug 31 '17 at 05:53