我花了一段时间环顾四周,似乎没有明显的解决方案。
我注册了程序集中的所有类型(大约有80种类型,接口在单独的程序集中)
public static void RegisterAllFromAssemblies(string a)
{
IoC.Container.Register(
AllTypes.FromAssemblyNamed(a)
.Pick()
.WithService.FirstInterface()
.Configure(o => o.LifeStyle.PerWebRequest)
);
}现在假设我想对其中一个对象使用不同的LifeStyle,我不能覆盖,因为我将获得--已经为给定的键错误注册了一个组件。
在这次注册之后,我已经研究了各种改变生活方式的方法,但是到目前为止,我还没能让任何东西发挥作用。
这里的理想解决方案应该是什么?我不想放弃AllTypes功能。
我想我可以在注册all时指定一个.Where过滤器,并跳过几个要手动注册的对象,但这不是一个非常进取的解决方案。
发布于 2013-11-27 08:54:47
这是否是您首先手动注册异常的一个选项?如果是这样的话,手动注册的组件将不会被“AllTypes”重新注册(我建议您使用类)。如果在“组”注册后手动注册组件,则会引发异常,但反之亦然。
例如
//YourImplementation lives in assembly 'a'
IoC.Container.Register(
Component.For<YourInterface>().ImplementedBy<YourImplementation>().LifestyleSingleton()
);
IoC.Container.Register(
Classes.FromAssemblyNamed(a)
.Pick()
.WithService.FirstInterface()
.Configure(o => o.LifeStyle.PerWebRequest)
);发布于 2013-11-27 01:11:21
我相信您是在程序集中注册所有类型,在程序集中的某些类型可能需要以不同的方式注册。因此,您可以得到IRepository,它需要是一个PerWebRequest,ITypeMapper可以是一个单独的。
我之所以澄清,也是因为您还想让IRepository在代码中的某个位置成为一个PerWebRequest,在另一个位置上是一个单独的对象。无需创建疯狂的生活方式,您可以创建组件并将其注册为默认的生活方式。如果您需要另一种生活方式,有时您可以创建一个新组件,并从现有组件继承,以便用于注册(代码示例显示了这一点,如果这令人困惑)。
我编写了这个示例,以便它能够适用于任何一个场景,并且我给出了几种不同的方法,它们都集中在同时配置多个项的过滤能力上。
对于这一项,我将按类型调用特定组件的配置。它并不像你所说的那样“活力”,但是如果你只有少数例外的话,它的意图就会更清楚。您将注意到您可以将配置链接在一起。除非是必需的,因为第二个配置将获取第一个配置的组件,即我的唯一条件是基于IService的服务。这假设城堡按顺序处理配置。我相信这个假设是正确的,但是已经有一段时间没有看过来源了。
container.Register(
Classes.FromThisAssembly()
.BasedOn<IService>()
.ConfigureFor<MyComponentAsSingleton>(component => component.LifestyleSingleton())
.Configure(component => component.LifestylePerWebRequest()).Unless(type => container.Kernel.GetAssignableHandlers(type).Count() > 0));这一项使用的属性更一般地偏离了正常生活方式"PerWebRequest“
container2.Register(
Classes.FromThisAssembly()
.BasedOn<IService>()
.ConfigureIf(
//condition to check - do we have our custom Attribute?
registration => registration.Implementation.GetCustomAttributes(false).Any(attr => typeof(ShouldBeSingleton).IsAssignableFrom(attr.GetType())),
//if true register as singleton
component => component.LifestyleSingleton(),
//else register as per web request
component => component.LifestylePerWebRequest()
));现在我已经给了你一些解决你眼前问题的例子(据我理解),让我免费给你我的建议!
首先,我不太喜欢WithService.FirstInterface()。正如智能声明的那样,实现多个接口是不确定的。任何开发人员都可以进入并对类进行无害的接口更改,然后破坏系统。如果您能够摆脱WithService.DefaultInterfaces(),那么解决方案就更难搞砸了。默认接口只是告诉城堡,在注册Foo组件时,如果服务IFoo实现了名为IFoo的接口,则使用它。
其次,我相信如果将注册逻辑划分为内聚单元,您可能不会遇到这个问题。关键是要有许多实现IWindsorInstaller的安装程序文件。在这些安装程序中,您只注册对特定安装程序有意义的类型(使用类或类型使其保持企业级)。在同一个安装程序中存在多种生活方式问题的可能性相当低(如果您发现这一点,您可能需要更多的安装程序)
如果您遵循这种方法,您最终可能会得到一个RepositoryInstaller、ViewInstaller、ControllerInstaller等有关安装程序的更多信息可以在城堡文档站点上找到。。
如果您想要的话,您可以做的是为您的所有系统设置一个通用的引导程序,它可以查看应用程序目录并安装目录中的所有安装程序。既然这不是你要求的,我就不再详细阐述了,但是如果你感兴趣的话,你可以告诉我,我可以给你看更多我在说什么。
完整的示例代码作为控制台应用程序:
using Castle.MicroKernel.Registration;
using Castle.Windsor;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace MultipleLifecyles
{
[AttributeUsage(AttributeTargets.Class)]
public class ShouldBeSingleton : Attribute
{
}
public interface IService
{
void DoSomething();
}
public class MyComponent : IService
{
public void DoSomething()
{
throw new NotImplementedException();
}
}
[ShouldBeSingleton]
public class MyComponentAsSingleton : MyComponent
{
}
class Program
{
static void Main(string[] args)
{
//option 1
IWindsorContainer container = new WindsorContainer();
container.Register(
Classes.FromThisAssembly()
.BasedOn<IService>()
.ConfigureFor<MyComponentAsSingleton>(component => component.LifestyleSingleton())
.Configure(component => component.LifestylePerWebRequest()).Unless(type => container.Kernel.GetAssignableHandlers(type).Count() > 0));
IWindsorContainer container2 = new WindsorContainer();
container2.Register(
Classes.FromThisAssembly()
.BasedOn<IService>()
.ConfigureIf(
//condition to check - do we have our custom Attribute?
registration => registration.Implementation.GetCustomAttributes(false).Any(attr => typeof(ShouldBeSingleton).IsAssignableFrom(attr.GetType())),
//if true register as singleton
component => component.LifestyleSingleton(),
//else register as per web request
component => component.LifestylePerWebRequest()
));
Console.ReadLine();
}
}
}https://stackoverflow.com/questions/20225312
复制相似问题