我知道SimpleInjector的LifestyleMismatch异常的目的以及它抛出它的原因。但是假设有:
Players.dll
public abstract class PlayerEqualizer { ... }
public abstract class Player : IPlayer, ISongAware
{
public Player(PlayerEqualizer eq)
{
Equalizer = eq;
}
public PlayerEqualizer Equalizer { get; }
public abstract void StartPlay();
}
Players.Rock.dll
public class RockPlayerEqualizer : PlayerEqualizer {}
public class RockPlayer : Player
{
public RockPlayer(RockPlayerEqualizer eq) : base(eq) {}
public override void StartPlay() { ... }
}
public class RnBPlayer : Player
{
public RnBPlayer(RockPlayerEqualizer eq) : base(eq) {}
public override void StartPlay() { ... }
}
Players.Pop.dll
public class PopPlayerEqualizer : PlayerEqualizer{}
public class PopPlayer : Player
{
public PopPlayer(PopPlayerEqualizer eq) : base(eq) {}
public override void StartPlay() { ... }
}
Player
的所有实施都被注册为IPlayer
的集合,所有注册都是单身:
var registrations = container
.GetTypesToRegister(typeof(IPlayer), assemblies)
.Select(t => Lifestyle.Singleton.CreateRegistration(t, container));
foreach (var registration in registrations)
{
container.AddRegistration(registration.ImplementationType, registration);
}
container.RegisterCollection<IPlayer>(registrations);
container.RegisterCollection<ISongAware>(container.GetCurrentRegistrations()
.Where(ip => typeof(ISongAware).IsAssignableFrom(ip.ServiceType))
.Select(ip => ip.Registration));
全部
container.GetInstance<RockPlayer>
container.GetAllInstances<IPlayer>
container.GetAllInstances<ISongAware>
必须返回相同的实例,因此IPlayer
注册必须是单例。这样做,所有PlayerEqualizer
也必须是单例,因为它们是单例注册的依赖关系,但PlayerEqualizer
实现不是单例(RockPlayer
和RnBPlayer
两者取决于RockPlayerEqualizer
,但它们需要不同的实例。)
我能找到的唯一解决方案是将SimpleInjector container.Options.SuppressLifestyleMismatchVerification
标志设置为False
,但我不想丢失该功能......另一种选择是调用SuppressDiagnosticWarning
关于IPlayer
注册的方法,但是尽管我无法使用它,我真正关心的是这些解决方案只是解决方法......
我错过了什么吗?
答案 0 :(得分:0)
你想要的是不将PlayerEqualizer
个实例注册为Transient,而是Instance Per Dependency。
从技术上讲,两种生活方式都是一样的,因为它们都会在每次请求时都返回新的实例。然而,每个依赖性实例的意图 非常不同,因为:
每个使用者都将获得给定服务类型的新实例,并且只要其消费类型,该依赖关系就会生效。
使用 Transient 时,意图是依赖是短暂的。
这种生活方式被故意排除在Simple Injector之外,因为:
与Transient生活方式相比,它的用处非常有限。它忽略了生活方式不匹配检查,这很容易导致错误,并忽略了应用程序组件应该是不可变的这一事实。如果一个组件是不可变的,那么每个消费者都不太可能需要它自己的注入依赖项实例。
项目的代码示例包含InstancePerDependencyLifestyle的定义,它可以执行您想要的操作:
您可以按照以下方式使用这种生活方式:
container.Register<RockPlayerEqualizer>(new InstancePerDependencyLifestyle());
<强>更新强>:
请注意,您的配置可以简化为以下内容:
var playerTypes = var registrations = container
.GetTypesToRegister(typeof(IPlayer), assemblies);
foreach (Type playerType in playerTypes)
{
container.Register(playerType, Lifestyle.Singleton);
}
container.RegisterCollection<IPlayer>(assemblies);
container.RegisterCollection<ISongAware>(assemblies);