在 Simple Injector 中混合生活方式和自动接线是否可以?
Is it okay to mix lifestyles with auto-wiring in Simple Injector
我正在使用 Simple Injector,。在我的 INotificationHandlers
自动布线期间,我允许针对不同的具体实现使用不同的生活方式,如下所示:
public static Lifestyle GetLifestyleForType(
Type type, Container container, Dictionary<Type,Lifestyle> list = null)
{
if (list is null) return container.Options.DefaultLifestyle;
return list.TryGetValue(type, out var lifestyle)
? lifestyle : container.Options.DefaultLifestyle;
}
public static void Wire(Container container)
{
var lifestyles = new Dictionary<Type, Lifestyle> {
{ typeof(FirstClass), Lifestyle.Singleton },
{ typeof(OtherClass), Lifestyle.Transient }
};
var handlerTypes = container
.GetTypesToRegister(typeof(INotificationHandler<>), typeof(OtherClass).Assembly);
var handlerProducers = (
from type in handlerTypes
from interfaceType in type.GetClosedTypesOf(typeof(INotificationHandler<>))
let producer = GetLifestyleForType(type, container, lifestyles)
.CreateProducer(interfaceType, type, container)
group new { type, producer } by interfaceType into interfaceGroup
select new
{
interfaceGroup.Key,
Value = (
from pair in interfaceGroup
group pair.producer by pair.type into concreteGroup
select new { concreteGroup.Key, Value = concreteGroup.ToArray() })
.ToDictionary(i => i.Key, i => i.Value)
}).ToDictionary(i => i.Key, i => i.Value);
}
我注意到所有其他自动接线示例,它假定使用相同的生活方式(因为没有看到指定的生活方式) - 任何原因(以防止做危险的事情)?
此外,Lifestyle.Transient
与 async/await
运算符的工作方式不同吗?刚刚意识到一直在使用 Transient
生命周期和 SimpleInjector
没有任何我知道的观察到的不良影响,假设我应该默认切换到 Lifestyle.Scoped
和container.Options.DefaultScopedLifestyle = new AsyncScopedLifestyle()
I note with all other auto-wiring examples, it assumes the same lifestyle is used (as haven't seen one specified) - any reason for this (to prevent doing dangerous things)?
默认情况下,Simple Injector 使用 Transient
作为其默认生活方式。这意味着,除非您明确提供生活方式注册,否则 Simple Injector 使用默认生活方式,即 Transient
.
虽然为您的处理程序使用多种生活方式本质上没有错,但使用多种生活方式确实会增加解决方案的复杂性(正如您可能已经注意到的那样),因此您应该问问自己是否真的需要这种复杂性。除非您希望使您的对象图从上到下成为单例(但这会导致 a completely different model),否则我建议保持解决方案简单并坚持使用 Transient
。作为一般经验法则,使您的根类型(处理程序、控制器、视图模型等)Transient
.
Transient
生活方式会带来一些后果。 Transient
个组件未被丢弃,并且由于 Transient
个组件未被重复使用,因此它们不能用于任何数据缓存。
但是这些问题可以通过将任何有关处置和缓存的逻辑移动到根类型的依赖项来轻松解决。您可以使这些依赖关系 Scoped
甚至 Singleton
。我通常不赞成系统中实现 IDisposable
或在内部缓存任何状态的任何处理程序。将这种逻辑移出您的处理程序 - 不仅 - 'works around' Transient
生活方式的局限性,我认为这会导致设计更好的系统。它还可以更轻松地推理您的处理程序;他们能做什么和不能做什么,以及他们的生活方式是什么。对于在系统上工作的任何开发人员(以及任何未来的开发人员)来说,最容易理解的是所有处理程序始终具有相同的生活方式。
In addition does Lifestyle.Transient work differently with async/await operators?
Transient
生活方式是最简单的生活方式;对于 Simple Injector Transient
只是一个空操作。实例已创建并被遗忘(未跟踪)。当 运行 在异步操作中时,它不会有任何不同。
我正在使用 Simple Injector,INotificationHandlers
自动布线期间,我允许针对不同的具体实现使用不同的生活方式,如下所示:
public static Lifestyle GetLifestyleForType(
Type type, Container container, Dictionary<Type,Lifestyle> list = null)
{
if (list is null) return container.Options.DefaultLifestyle;
return list.TryGetValue(type, out var lifestyle)
? lifestyle : container.Options.DefaultLifestyle;
}
public static void Wire(Container container)
{
var lifestyles = new Dictionary<Type, Lifestyle> {
{ typeof(FirstClass), Lifestyle.Singleton },
{ typeof(OtherClass), Lifestyle.Transient }
};
var handlerTypes = container
.GetTypesToRegister(typeof(INotificationHandler<>), typeof(OtherClass).Assembly);
var handlerProducers = (
from type in handlerTypes
from interfaceType in type.GetClosedTypesOf(typeof(INotificationHandler<>))
let producer = GetLifestyleForType(type, container, lifestyles)
.CreateProducer(interfaceType, type, container)
group new { type, producer } by interfaceType into interfaceGroup
select new
{
interfaceGroup.Key,
Value = (
from pair in interfaceGroup
group pair.producer by pair.type into concreteGroup
select new { concreteGroup.Key, Value = concreteGroup.ToArray() })
.ToDictionary(i => i.Key, i => i.Value)
}).ToDictionary(i => i.Key, i => i.Value);
}
我注意到所有其他自动接线示例,它假定使用相同的生活方式(因为没有看到指定的生活方式) - 任何原因(以防止做危险的事情)?
此外,Lifestyle.Transient
与 async/await
运算符的工作方式不同吗?刚刚意识到一直在使用 Transient
生命周期和 SimpleInjector
没有任何我知道的观察到的不良影响,假设我应该默认切换到 Lifestyle.Scoped
和container.Options.DefaultScopedLifestyle = new AsyncScopedLifestyle()
I note with all other auto-wiring examples, it assumes the same lifestyle is used (as haven't seen one specified) - any reason for this (to prevent doing dangerous things)?
默认情况下,Simple Injector 使用 Transient
作为其默认生活方式。这意味着,除非您明确提供生活方式注册,否则 Simple Injector 使用默认生活方式,即 Transient
.
虽然为您的处理程序使用多种生活方式本质上没有错,但使用多种生活方式确实会增加解决方案的复杂性(正如您可能已经注意到的那样),因此您应该问问自己是否真的需要这种复杂性。除非您希望使您的对象图从上到下成为单例(但这会导致 a completely different model),否则我建议保持解决方案简单并坚持使用 Transient
。作为一般经验法则,使您的根类型(处理程序、控制器、视图模型等)Transient
.
Transient
生活方式会带来一些后果。 Transient
个组件未被丢弃,并且由于 Transient
个组件未被重复使用,因此它们不能用于任何数据缓存。
但是这些问题可以通过将任何有关处置和缓存的逻辑移动到根类型的依赖项来轻松解决。您可以使这些依赖关系 Scoped
甚至 Singleton
。我通常不赞成系统中实现 IDisposable
或在内部缓存任何状态的任何处理程序。将这种逻辑移出您的处理程序 - 不仅 - 'works around' Transient
生活方式的局限性,我认为这会导致设计更好的系统。它还可以更轻松地推理您的处理程序;他们能做什么和不能做什么,以及他们的生活方式是什么。对于在系统上工作的任何开发人员(以及任何未来的开发人员)来说,最容易理解的是所有处理程序始终具有相同的生活方式。
In addition does Lifestyle.Transient work differently with async/await operators?
Transient
生活方式是最简单的生活方式;对于 Simple Injector Transient
只是一个空操作。实例已创建并被遗忘(未跟踪)。当 运行 在异步操作中时,它不会有任何不同。