关于.net:Castle Windsor:如何从代码中指定构造函数参数?

关于.net:Castle Windsor:如何从代码中指定构造函数参数?

Castle Windsor: How to specify a constructor parameter from code?

说我有以下课程

1
2
3
MyComponent : IMyComponent {
  public MyComponent(int start_at) {...}
}

我可以通过xml向城堡温莎注册它的一个实例,如下所示

1
2
3
4
5
<component id="sample"  service="NS.IMyComponent, WindsorSample" type="NS.MyComponent, WindsorSample">  
  <parameters>  
    <start_at>1</start_at >  
  </parameters>  
</component>

我将如何用代码做完全相同的事情? (注意,构造函数参数)


编辑:在Fluent界面中使用以下代码的答案:)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
namespace WindsorSample
{
    using Castle.MicroKernel.Registration;
    using Castle.Windsor;
    using NUnit.Framework;
    using NUnit.Framework.SyntaxHelpers;

    public class MyComponent : IMyComponent
    {
        public MyComponent(int start_at)
        {
            this.Value = start_at;
        }

        public int Value { get; private set; }
    }

    public interface IMyComponent
    {
        int Value { get; }
    }

    [TestFixture]
    public class ConcreteImplFixture
    {
        [Test]
        void ResolvingConcreteImplShouldInitialiseValue()
        {
            IWindsorContainer container = new WindsorContainer();

            container.Register(
                Component.For<IMyComponent>()
                .ImplementedBy<MyComponent>()
                .Parameters(Parameter.ForKey("start_at").Eq("1")));

            Assert.That(container.Resolve<IMyComponent>().Value, Is.EqualTo(1));
        }

    }
}

尝试这个

1
2
int start_at = 1;
container.Register(Component.For().DependsOn(dependency: Dependency.OnValue(start_at)));


您是否考虑过使用Binsor配置容器?您可以使用基于Boo的DSL配置Windsor,而不是冗长而笨拙的XML。这是您的配置如下所示:

1
2
component IMyComponent, MyComponent:
   start_at = 1

优点是您拥有可延展的配置文件,但避免了XML问题。另外,您不必重新编译即可更改配置,就像您在代码中配置容器一样。

还有许多辅助方法可以实现零摩擦配置:

1
2
3
4
  for type in Assembly.Load("MyApp").GetTypes():
    continue unless type.NameSpace =="MyApp.Services"
    continue if type.IsInterface or type.IsAbstract or type.GetInterfaces().Length == 0
    component type.GetInterfaces()[0], type

您可以在这里开始使用。


您可以使用配置类来读取app.config。然后注册并获得windsor对其依赖使用。理想情况下,我的MyConfiguration将使用接口。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
public class MyConfiguration
{
    public long CacheSize { get; }

    public MyConfiguration()
    {
        CacheSize = ConfigurationManager.AppSettings["cachesize"].ToLong();
    }
}



container.Register(Component.For<MyConfiguration>().ImplementedBy<MyConfiguration>());

container.Register(Component.For<MostRecentlyUsedSet<long>>()
.ImplementedBy<MostRecentlyUsedSet<long>>().
DependsOn(Dependency.OnValue("size", container.Resolve<MyConfiguration>().CacheSize))
.LifestyleSingleton());

当您向容器询问实例时,您需要传递IDictionary。

您将使用IWindsorContainer的以下Resolve重载:

1
T Resolve< T >(IDictionary arguments)

或非通用的:

1
object Resolve(Type service, IDictionary arguments)

因此,例如:(假设容器是IWindsorContainer)

1
2
3
IDictionary<string, object> values = new Dictionary<string, object>();
values["start_at"] = 1;
container.Resolve<IMyComponent>(values);

请注意,字典中的键值区分大小写。


您可以使用IWindsorContainer接口的AddComponentWithProperties方法来注册具有扩展属性的服务。

以下是使用NUnit单元测试执行此操作的"有效"示例。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
namespace WindsorSample
{
    public class MyComponent : IMyComponent
    {
        public MyComponent(int start_at)
        {
            this.Value = start_at;
        }

        public int Value { get; private set; }
    }

    public interface IMyComponent
    {
        int Value { get; }
    }

    [TestFixture]
    public class ConcreteImplFixture
    {
        [Test]
        void ResolvingConcreteImplShouldInitialiseValue()
        {
            IWindsorContainer container = new WindsorContainer();
            IDictionary parameters = new Hashtable {{"start_at", 1}};

            container.AddComponentWithProperties("concrete", typeof(IMyComponent), typeof(MyComponent), parameters);

            IMyComponent resolvedComp = container.Resolve<IMyComponent>();

            Assert.That(resolvedComp.Value, Is.EqualTo(1));
        }

    }
}


推荐阅读

    linux命令基础代码?

    linux命令基础代码?,基础,系统,管理,工作,代码,网络,单位,信息,数据,命令,lin

    linux打开代码命令行?

    linux打开代码命令行?,系统,首页,工具,终端,代码,密码,情况,命令,快捷键,窗

    linux命令指定jdk?

    linux命令指定jdk?,系统,官网,工具,状态,一致,底部,情况,环境变量,路径,文件

    linux克隆代码命令?

    linux克隆代码命令?,系统,代码,文件,命令,目录,源文件,文件夹,路径,目标,表

    linux命令行调试代码?

    linux命令行调试代码?,环境,代码,信息,平台,程序,编辑,版本,步骤,体系结构,

    linux编译源代码命令?

    linux编译源代码命令?,工具,代码,百度,最新,环境,项目,系统,电脑,密码,内核,l

    linux命令提交代码?

    linux命令提交代码?,工作,系统,地址,代码,命令,数据,信息,目录,标准,发行,求

    linux代码同步命令?

    linux代码同步命令?,时间,服务,系统,地址,代码,网络,通信,图片,风险,管理,lin

    linux命令错误代码?

    linux命令错误代码?,系统,密码,电脑,网络,手机,网址,软件,代码,设备,老板,Lin

    linux同步代码命令?

    linux同步代码命令?,时间,系统,通信,网络,标准,图片,服务,代码,线程,单位,Lin

    linux拉取代码命令?

    linux拉取代码命令?,代码,工作,地址,命令,数据,系统,单位,生产,软件,目录,lin

    linux代码对齐命令?

    linux代码对齐命令?,系统,地址,标准,信息,对比,名称,代码,命令,文件,工作,lin

    linux命令运行代码?

    linux命令运行代码?,代码,单位,系统,环境,连续,保险,工具,命令,文件,音乐,Lin

    linux命令跳到指定行?

    linux命令跳到指定行?,地址,工作,系统,信息,命令,发行,位置,管理,情况,目录,l

    搭建linux命令行代码?

    搭建linux命令行代码?,系统,软件,工作,名字,服务,代码,地址,环境,管理,密码,l

    linux查看命令代码?

    linux查看命令代码?,系统,信息,代码,名称,命令,设备,数字,第一,软件,管理,在L

    linux删除代码命令行?

    linux删除代码命令行?,系统,代码,命令,文件,不了,环境,档案,名称,目录,文件

    linux指定显示屏命令?

    linux指定显示屏命令?,工具,系统,命令,代码,实时,技术,内容,文件,管道,两个,

    linux命令行代码实现?

    linux命令行代码实现?,标准,代码,管理,网络,地址,工作,命令,网上,环境,名称,

    linux桌面命令代码?

    linux桌面命令代码?,电脑,系统,密码,环境,代码,基础,地址,服务,网上,通讯,lin