dadhi / DryIoc

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

'WithConcreteTypeDynamicRegistrations' results in unintended instantiation #643

Open A-Kjeldgaard opened 4 months ago

A-Kjeldgaard commented 4 months ago

Using the WithConcreteTypeDynamicRegistrations(), when injecting a range of class, where no registrations has been added, results in instantation of an item.

Other scenarios:

  1. When using WithAutoConcreteTypeResolution the issue does not occur.
  2. If item has been registered, then issue does not occur.
  3. Other range interfaces (IList, ICollection etc.) results in same issue.
  4. Injecting a range of interfaces (eg. IThing), the issue does not occur.

Setup:

class Program
{
  void Main()
  {
    var rules = Rules
        .Default
        //.WithAutoConcreteTypeResolution()
        .WithConcreteTypeDynamicRegistrations();

    var container = new Container(rules);
    container.Register<MyRegistry>();

    var registry = container.Resolve<MyRegistry>();
  }
}

class MyRegistry
{
  public MyRegistry(IEnumerable<Thing> things)
  {
    /* 'things' contains a single thing */
    Debugger.Break();
  }
}
class Thing
{
  Guid Id { get; set; }
}

Expected Behavior: 'things' should be empty.

Current behavior: 'things' contain a single item.

dadhi commented 4 months ago

@A-Kjeldgaard, thank you for the example and the detailed description. I will look.

dadhi commented 4 months ago

@A-Kjeldgaard What do you mean by this?

If item has been registered, then issue does not occur.

If I am registering Thing then it will appear in the injected collection as intended.

As I understood, you would like to avoid automatic concrete type instantiation with WithConcreteTypeDynamicRegistrations, right?

BTW, WithAutoConcreteTypeResolution works this way because they do not Wrappers in general, including the collection one.

A-Kjeldgaard commented 4 months ago

My expectation is: if there is no registrations where the service type is type Thing, then no elements should appear when injecting a collection/enumerable/list.

If I add registrations for Thing, I would expect one item in the injected collection for each registration added.

Examples of registrations:

container.RegisterInstance(new Thing { Id = Guid.NewGuid() });
container.RegisterDelegate(rc => new Thing { Id = Guid.NewGuid() });
container.Register<Thing>();

If I was to inject Thing directly, as such:

public MyRegistry(Thing thing) { ... }

Then I would expect the container to instantiate an instance of Thing.

So to sum up, I only expect dynamic registrations to result in an instance when service type is directly requested, not when inside a range type.