class 的两个接口在简单注入器中注册为单例的行为是什么

What is a behavior of a class with two interfaces registered as singleton in simple injector

我有一个关注 class:

public class UserService : IUserService, IObserver<User>

我已将 IUserService 注册为 UserService 的单身人士。之后我以这种方式注册 IObserver

container.RegisterManyForOpenGeneric(typeof(IObserver<>),
    container.RegisterAll,
    typeof(IObserver<>).Assembly);

所以现在,如果我将 IEnumerable<IObservable> 注入到我的复合模式中,当我枚举时,我会得到与解析 IUserService 时相同的对象吗?

它似乎以这种方式工作(只有一个 UserService 对象存在)至少如果我首先解决 IEnumerable 。我无法在文档中找到它,但这是 Simple Injector 支持的功能还是可以随时更改的巧合?如果是,那么我想这种行为对于任何两个或更多接口都是相同的,不一定是开放通用的?

您看到的行为是设计使然,并在 container.RegisterCollection(Type, IEnumerable) method(v2.x 中的RegisterAll)的文档中进行了描述:

Registers a collection of serviceTypes, whose instances will be resolved lazily each time the resolved collection of serviceType is enumerated. The underlying collection is a stream that will return individual instances based on their specific registered lifestyle, for each call to IEnumerator<T>.Current. The order in which the types appear in the collection is the exact same order that the items were registered, i.e the resolved collection is deterministic.

尽管 API 文档说明了这一点,但我必须承认文档对此不是很清楚。 other places 描述了此行为,但此信息有点深藏在文档中。

但基本上,API 旨在允许:

container.Register<ILogger, DefaultLogger>(Lifestyle.Transient);
container.Register<SqlLogger>(Lifestyle.Scoped);
container.Register<FileLogger>(Lifestyle.Singleton);

container.RegisteCollection<ILogger>(new[] {
    typeof(MailLogger), 
    typeof(SqlLogger), 
    typeof(FileLogger),
    typeof(ILogger)
 });

此配置有一个 ILogger 实现的集合,其中集合中的第一个元素 (MailLogger) 将是一个瞬态元素(以防 LifestyleSelectionBehavior 未被覆盖) ,第二个 (SqlLogger) 将是 Per Request,第三个 (FileLogger) 将是一个单例,第四个元素将 DefaultLogger 解析为瞬态。

it's a coincidence that can be changed at any time?

不,这是有记录、测试和支持的。尽管我们将(在 definition 之前)在下一个主要版本中引入重大更改,但我们不太可能更改此行为。

更新:请注意,此行为在 v3 中没有改变。

when you have two interfaces on the same class: will it will be the same class if I register the second interface on the same class?

不,不会。这实际上会导致 Torn Registration, which is something the Diagnostic Services 警告。基本上,如果你这样做:

container.Register<IFoo, FooBar>(Lifestyle.Singleton);
container.Register<IBar, FooBar>(Lifestyle.Singleton);

在这种情况下,容器将为 FooBar 解析两个单独的实例。那是因为 Simple Injector 专注于注册(抽象),而不是实现(例如,与 Unity 相比,它以相反的方式工作)。如果您恰好需要 1 FooBar,则必须执行以下操作:

var registration = Lifestyle.Singleton.CreateRegistration<FooBar>(container);

container.AddRegistration(typeof(IFoo), registration);
container.AddRegistration(typeof(IBar), registration);

在你的情况下,这意味着你必须这样做:

var registration = Lifestyle.Singleton.CreateRegistration<UserService>(container);

container.AddRegistration(typeof(IUserService), registration);
container.AddRegistration(typeof(UserService), registration);

container.RegisterCollection(typeof(IObserver<>),
    new[] { typeof(IObserver<>).Assembly });

// Simple Injector v2.x syntax
container.RegisterManyForOpenGeneric(typeof(IObserver<>),
    container.RegisterAll,
    typeof(IObserver<>).Assembly);