structuremap / structuremap

A Dependency Injection/Inversion of Control tool for .NET
http://structuremap.github.com
Other
911 stars 275 forks source link

Support IReadOnlyCollection<T> for injection #586

Open AnotherICe opened 7 years ago

AnotherICe commented 7 years ago

C# 4.0 introduced some new collection types, for example IReadOnlyCollection, IReadOnlyList. Usage of this types is preffered for respective immutable types. Ususally immutable types (services, decorators, etc) use consturctor injection, but structuremap cannot resolve this types using this mechanism. Can you add support for this types?

Reasons:

  1. If we use IList, we will give misguiding interface - we cannot interfere with underlying list of objects from the object list being injected into.
  2. If we don't want to use IList / ICollection and we use IEnumerable, we have to use .ToArray() (or similar transformation) to escape usage of deferred execution.
DixonDs commented 7 years ago

@AnotherICe Won't it work if you just register ReadOnlyCollection for IReadOnlyCollection/ IReadOnlyList since ReadOnlyCollection ctor accepts IList<> which is already registered? Something as follows

For(typeof(IReadOnlyList<>)).Use(typeof(ReadOnlyCollection<>));
AnotherICe commented 7 years ago

Its works fine for most cases, but it fails when we try to use EnumerateOf method for StartInstance. Its look like it skip this registration and just try to resolve all known instances.

Sample pseudo-code

// try fix registration
For(typeof(IReadOnlyList<>)).Use(typeof(ReadOnlyCollection<>));

// register common dependencies
var instance1 = For<IWorksheetProcessor>.Use<WorksheetProcessor1>();
var instance2 = For<IWorksheetProcessor>.Use<WorksheetProcessor2>();
For<IWorkbookProcessor>.Use<WorkbookProcessor>().EnumerateOf<IWorksheetProcessor>.Contains(x => x.Instance(instance1));

// try use
var workbookProcessor = GetInstance<WorkbookProcessor>();
// NOTE: workbookProcessor.WorksheetProcessors contains WorksheetProcessor1 and WorksheetProcessor2