В SimpleInjector documentation сказано:SimpleInjector неожиданное поведение явно зарегистрированного одноплодной коллекции
Простой Инжектор сохраняет образ жизни экземпляров, которые возвращаются из впрыскивается
IEnumerable<T>
,ICollection<T>
,IList<T>
,IReadOnlyCollection<T>
иIReadOnlyList<T>
экземпляра. На самом деле вы не должны видеть введенныйIEnumerable<T>
в качестве коллекции экземпляров; вы должны рассматривать это поток инстанций. Простой Injector всегда впрыснуть ссылку на тот же поток (IEnumerable<T>
или самICollection<T>
одноэлементно) и каждый раз вы итерируетеIEnumerable<T>
, для каждого отдельного компонента, то контейнер просит разрешить пример, основанный на образе жизни этот компонент.
После прочтения этого я ожидал, что после того, как я зарегистрировал все IFoo
и IFoo<T>
как одиночки, IEnumerable<IFoo>
будет одноточечно сам и перечисление всегда будет приводить к тем же объектам.
Но этот кусок кода не работает так:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using SimpleInjector;
class Program
{
interface IFoo{}
interface IFoo<T> : IFoo{}
class Foo : IFoo<Foo>{}
class Consumer1
{
public IFoo<Foo> FooInstance { get; }
public Consumer1(IFoo<Foo> fooInstance){FooInstance = fooInstance;}
}
class Consumer2
{
public IFoo<Foo> FooInstance { get; }
public Consumer2(IFoo<Foo> fooInstance){FooInstance = fooInstance;}
}
class Consumer3
{
public IEnumerable<IFoo> FooIntances { get; }
public Consumer3(IEnumerable<IFoo> fooIntances){FooIntances = fooIntances;}
}
static void Main(string[] args)
{
var cont = new Container();
var types = Assembly.GetExecutingAssembly()
.GetTypes()
.Where(x =>
typeof(IFoo<>).IsAssignableFrom(x) ||
typeof(IFoo).IsAssignableFrom(x))
.Where(x => !x.IsInterface);
foreach (var type in types)
{
var genericFoo = type.GetInterfaces().Single(x=>x.IsGenericType);
var genericArgs = genericFoo.GenericTypeArguments;
var closedGenericFoo = typeof(IFoo<>).MakeGenericType(genericArgs);
var reg = Lifestyle.Singleton.CreateRegistration(type, cont);
cont.AddRegistration(closedGenericFoo, reg);
cont.AddRegistration(typeof(IFoo), reg);
}
cont.RegisterCollection<IFoo>(new[] {Assembly.GetExecutingAssembly()});
var cons1 = cont.GetInstance<Consumer1>();
var cons2 = cont.GetInstance<Consumer2>();
var cons3_1 = cont.GetInstance<Consumer3>();
var cons3_2 = cont.GetInstance<Consumer3>();
// Expected: true | Actually: true
Console.WriteLine($"cons1.FooInstance == cons2.FooInstance : {cons1.FooInstance == cons2.FooInstance}");
// Expected: true | Actually: true
Console.WriteLine($"cons3_1.FooInstances == cons3_2.FooInstances : {cons3_1.FooIntances == cons3_2.FooIntances}");
// Expected: true | Actually: false
Console.WriteLine($"cons3_1.FooIntances.First() == cons1.FooInstance : {cons3_1.FooIntances.First() == cons1.FooInstance}");
// Expected: true | Actually: false
Console.WriteLine($"cons3_1.FooIntances.First() == cons3_2.FooIntances.First() : {cons3_1.FooIntances.First() == cons3_2.FooIntances.First()}");
Console.ReadKey();
}
}
То, что я пытаюсь достичь:
- одного
Foo
реализации зарегистрирована какIFoo<Foo>
иIFoo
(частично работ) - одиночный поток
IFoo
которыйIEnumerable<IFoo>
(он работает) - Итерация из
IEnumerable
выше должен дать мне тот жеFoo
реализации (не работает)
Возможно ли это?
Пожалуйста, позвоните 'Container.Verify()' в конце фазы регистрации. Это приведет к исключению, которое объясняет, почему ваши ожидания не выполняются. – Steven
@Steven это не так :) Он сказал, что у меня есть 3 регистрации для 'Foo': 1) Singleton' IFoo', 2) Singleton 'IFoo' и 3) Transient 'IFoo'. Третий вышел из ниоткуда. Это объясняет, почему 'IEnumerable ' каждый раз создает новый 'IFoo', но не объясняет, как я могу избежать временной регистрации' IFoo' –
Szer