为什么Castle Windsor类型工厂在使用不同参数创建时返回相同的实例

use*_*422 6 c# castle-windsor

在使用类型化的工厂设施时,我希望以下内容生成两个单独的实例.

using System;
using Castle.Facilities.TypedFactory;
using Castle.MicroKernel.Registration;
using Castle.Windsor;

namespace ConsoleApplication
{
    class Program
    {
        static void Main(string[] args)
        {
            var container = new WindsorContainer();

            container.AddFacility<TypedFactoryFacility>();

            container.Register(Component
                .For<IFactory>()
                .AsFactory()
                .LifestyleSingleton());

            container.Register(Component
                .For<IImplementation>()
                .ImplementedBy<Implementation>()
                .LifestylePerThread());

            var factory = container.Resolve<IFactory>();
            var implementation1 = factory.Create(1);
            var implementation2 = factory.Create(2);

            Console.WriteLine(implementation1 == implementation2);//Returns true!
            Console.Read();
        }
    }

    public interface IFactory
    {
        IImplementation Create(int dependency);
    }

    public interface IImplementation
    {}

    public class Implementation : IImplementation
    {
        private readonly int _dependency;

        public Implementation(int dependency)
        {
            _dependency = dependency;
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

我也尝试使用参数作为引用类型覆盖.Equals().GetHashCode()不是int但它没有区别.

我意识到我可以LifestyleTransient用来解决这个问题,但如果我传入相同的参数,我实际上想要接收相同的实例.

Phi*_*rdt 3

你的期望是不正确的。

当且仅当容器中尚不存在所需服务的组件时,传递给工厂方法的参数是用于构造新组件的详细信息。

您的第二个请求是从同一线程发出的,并且针对同一服务,因此 Windsor 正确返回已构造的请求。

虽然吉拉德的建议是可以遵循的,但您可能仍然会发现自己在与容器“斗争”,并使事情变得比需要的更加复杂。

我建议您采用 Windsor 中可用的机制,该机制完全依赖于服务类型(接口)来区分彼此的服务。

问问自己这两个实例有什么不同,并反映在接口方面的这些差异。例如,也许你应该有一个IBigImplementationand ISmallImplementation?然后可以在容器中注册和配置这些不同服务的实现;你得到了你想要的所有池化/重用;并且使用代码仍然幸福地不知道并且与实现细节分离。

[咆哮:虽然工厂允许更大的灵活性,但通常我认为对工厂方法使用参数是一种代码味道。正如您所发现的,它要求消费者对服务实现的生命周期做出假设。这也意味着控制实现细节的杠杆和开关分散在代码库中,而不是全部在容器注册代码中集中管理。]