在使用类型化的工厂设施时,我希望以下内容生成两个单独的实例.
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用来解决这个问题,但如果我传入相同的参数,我实际上想要接收相同的实例.
你的期望是不正确的。
当且仅当容器中尚不存在所需服务的组件时,传递给工厂方法的参数是用于构造新组件的详细信息。
您的第二个请求是从同一线程发出的,并且针对同一服务,因此 Windsor 正确返回已构造的请求。
虽然吉拉德的建议是可以遵循的,但您可能仍然会发现自己在与容器“斗争”,并使事情变得比需要的更加复杂。
我建议您采用 Windsor 中可用的机制,该机制完全依赖于服务类型(接口)来区分彼此的服务。
问问自己这两个实例有什么不同,并反映在接口方面的这些差异。例如,也许你应该有一个IBigImplementationand ISmallImplementation?然后可以在容器中注册和配置这些不同服务的实现;你得到了你想要的所有池化/重用;并且使用代码仍然幸福地不知道并且与实现细节分离。
[咆哮:虽然工厂允许更大的灵活性,但通常我认为对工厂方法使用参数是一种代码味道。正如您所发现的,它要求消费者对服务实现的生命周期做出假设。这也意味着控制实现细节的杠杆和开关分散在代码库中,而不是全部在容器注册代码中集中管理。]
| 归档时间: |
|
| 查看次数: |
1067 次 |
| 最近记录: |