わかりました、これを行うための非常にクリーンな方法を見つけました!
まず、の実装が必要ですIHandlerSelector
。これにより、問題に関する意見に基づいてハンドラーを選択するか、中立を保つことができます(null
「意見なし」を意味する、を返すことによって)。
/// <summary>
/// Emits an opinion about a component's lifestyle only if there are exactly two available handlers and one of them has a PerWebRequest lifestyle.
/// </summary>
public class LifestyleSelector : IHandlerSelector
{
public bool HasOpinionAbout(string key, Type service)
{
return service != typeof(object); // for some reason, Castle passes typeof(object) if the service type is null.
}
public IHandler SelectHandler(string key, Type service, IHandler[] handlers)
{
if (handlers.Length == 2 && handlers.Any(x => x.ComponentModel.LifestyleType == LifestyleType.PerWebRequest))
{
if (HttpContext.Current == null)
{
return handlers.Single(x => x.ComponentModel.LifestyleType != LifestyleType.PerWebRequest);
}
else
{
return handlers.Single(x => x.ComponentModel.LifestyleType == LifestyleType.PerWebRequest);
}
}
return null; // we don't have an opinion in this case.
}
}
私はそれを作ったので、意見は意図的に非常に限られています。PerWebRequest
ハンドラーがちょうど2人いて、そのうちの1人がライフスタイルを持っている場合にのみ意見を述べます。もう1つは、おそらくHttpContext以外の代替手段であることを意味します。
このセレクターをCastleに登録する必要があります。他のコンポーネントの登録を開始する前にこれを行います。
container.Kernel.AddHandlerSelector(new LifestyleSelector());
最後に、これを回避するために登録をコピーする方法についての手がかりがあればいいのにと思います。
container.Register(
AllTypes
.FromAssemblyContaining<EmailService>()
.Where(t => t.Name.EndsWith("Service"))
.WithService.Select(IoC.SelectByInterfaceConvention)
.LifestylePerWebRequest()
);
container.Register(
AllTypes
.FromAssemblyContaining<EmailService>()
.Where(t => t.Name.EndsWith("Service"))
.WithService.Select(IoC.SelectByInterfaceConvention)
.LifestylePerThread()
);
登録のクローンを作成し、ライフスタイルを変更し、両方を(またはのいずれcontainer.Register
かを使用してIRegistration.Register
)登録する方法を見つけられた場合は、ここに回答として投稿してください。:)
更新:テストでは、同じ登録に一意の名前を付ける必要があります。次のようにしました。
.NamedRandomly()
public static ComponentRegistration<T> NamedRandomly<T>(this ComponentRegistration<T> registration) where T : class
{
string name = registration.Implementation.FullName;
string random = "{0}{{{1}}}".FormatWith(name, Guid.NewGuid());
return registration.Named(random);
}
public static BasedOnDescriptor NamedRandomly(this BasedOnDescriptor registration)
{
return registration.Configure(x => x.NamedRandomly());
}