首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >温莎城堡生活方式配置

温莎城堡生活方式配置
EN

Stack Overflow用户
提问于 2013-11-26 18:41:29
回答 2查看 1.3K关注 0票数 0

我花了一段时间环顾四周,似乎没有明显的解决方案。

我注册了程序集中的所有类型(大约有80种类型,接口在单独的程序集中)

代码语言:javascript
复制
    public static void RegisterAllFromAssemblies(string a)
    {
        IoC.Container.Register(
            AllTypes.FromAssemblyNamed(a)
                .Pick()
                .WithService.FirstInterface()
                .Configure(o => o.LifeStyle.PerWebRequest)
            );
    }

现在假设我想对其中一个对象使用不同的LifeStyle,我不能覆盖,因为我将获得--已经为给定的键错误注册了一个组件。

在这次注册之后,我已经研究了各种改变生活方式的方法,但是到目前为止,我还没能让任何东西发挥作用。

这里的理想解决方案应该是什么?我不想放弃AllTypes功能。

我想我可以在注册all时指定一个.Where过滤器,并跳过几个要手动注册的对象,但这不是一个非常进取的解决方案。

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2013-11-27 08:54:47

这是否是您首先手动注册异常的一个选项?如果是这样的话,手动注册的组件将不会被“AllTypes”重新注册(我建议您使用类)。如果在“组”注册后手动注册组件,则会引发异常,但反之亦然。

例如

代码语言:javascript
复制
//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)
    );
票数 1
EN

Stack Overflow用户

发布于 2013-11-27 01:11:21

我相信您是在程序集中注册所有类型,在程序集中的某些类型可能需要以不同的方式注册。因此,您可以得到IRepository,它需要是一个PerWebRequest,ITypeMapper可以是一个单独的。

我之所以澄清,也是因为您还想让IRepository在代码中的某个位置成为一个PerWebRequest,在另一个位置上是一个单独的对象。无需创建疯狂的生活方式,您可以创建组件并将其注册为默认的生活方式。如果您需要另一种生活方式,有时您可以创建一个新组件,并从现有组件继承,以便用于注册(代码示例显示了这一点,如果这令人困惑)。

我编写了这个示例,以便它能够适用于任何一个场景,并且我给出了几种不同的方法,它们都集中在同时配置多个项的过滤能力上。

对于这一项,我将按类型调用特定组件的配置。它并不像你所说的那样“活力”,但是如果你只有少数例外的话,它的意图就会更清楚。您将注意到您可以将配置链接在一起。除非是必需的,因为第二个配置将获取第一个配置的组件,即我的唯一条件是基于IService的服务。这假设城堡按顺序处理配置。我相信这个假设是正确的,但是已经有一段时间没有看过来源了。

代码语言:javascript
复制
container.Register(
    Classes.FromThisAssembly()
        .BasedOn<IService>()
        .ConfigureFor<MyComponentAsSingleton>(component => component.LifestyleSingleton())
        .Configure(component => component.LifestylePerWebRequest()).Unless(type => container.Kernel.GetAssignableHandlers(type).Count() > 0));

这一项使用的属性更一般地偏离了正常生活方式"PerWebRequest“

代码语言:javascript
复制
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等有关安装程序的更多信息可以在城堡文档站点上找到。

如果您想要的话,您可以做的是为您的所有系统设置一个通用的引导程序,它可以查看应用程序目录并安装目录中的所有安装程序。既然这不是你要求的,我就不再详细阐述了,但是如果你感兴趣的话,你可以告诉我,我可以给你看更多我在说什么。

完整的示例代码作为控制台应用程序:

代码语言:javascript
复制
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();
        }
    }
}
票数 4
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/20225312

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档