msw*_*cki 16 c# castle-windsor
为什么要使用Castle Windsor工厂自动实现功能:AsFactory()而不是要求所需的接口?
例:
container.Register(Component.For<IEmailSender>().ImplementedBy<SmtpEmailSender>());
container.Register(Component.For<IEmailSenderFactory>().AsFactory().LifeStyle.Transient);
Run Code Online (Sandbox Code Playgroud)
...
using (var factory = context.GetServiceFactory<IEmailSenderFactory>())
{
var emailSender = factory.CreateEmailSender();
emailSender.Send(message);
}
Run Code Online (Sandbox Code Playgroud)
你为什么不写简单:
var emailSender = context.GetServiceFactory<IEmailSender>();
emailSender.Send(message);
Run Code Online (Sandbox Code Playgroud)
效果是一样的.Windsor会将IEmailSender解析为默认的注册实现,那么重点是什么呢?
Pat*_*irk 41
有时,当您需要解决它时,您将编写一个需要特定值的类.例如:
public class NumberWriter : INumberWriter
{
readonly int number;
readonly IStream stream;
public NumberWriter(int number, IStream stream)
{
this.number = number;
this.stream = stream;
}
public Write()
{
stream.Write(number);
}
}
Run Code Online (Sandbox Code Playgroud)
如果没有a number,你就无法解析这个类的实例,也许你也想指定stream(控制台,文件,打印机等等).所以,你定义一个工厂:
public interface INumberWriterFactory
{
INumberWriter Create(int number);
INumberWriter Create(int number, IStream stream);
}
Run Code Online (Sandbox Code Playgroud)
现在,以下代码将起作用:
public class RandomNumberGenerator
{
readonly INumberWriterFactory numberWriterFactory;
public RandomNumberGenerator(INumberWriterFactory numberWriterFactory)
{
this.numberWriterFactory = numberWriterFactory;
}
public void Generate()
{
Random random = new Random();
for (int i = 0; i < 10; i++)
{
// Writes to first IStream that Castle can resolve
var numberWriter = numberWriterFactory.Create(random.Next());
numberWriter.Write();
}
}
public void Generate(IStream stream)
{
Random random = new Random();
for (int i = 0; i < 10; i++)
{
// Writes to the given IStream
var numberWriter = numberWriterFactory.Create(random.Next(), stream);
numberWriter.Write();
}
}
}
Run Code Online (Sandbox Code Playgroud)
使用工厂可以使您无需更改创建对象的方式.例如,如果您需要创建对象的实例并且每次都使用相同的构造函数参数,则可以创建一个具体的工厂,然后只使用它到处而不是通过生成的那个AsFactory().
换句话说,我们可以通过stream在工厂中隐藏参数来修改某些代码的行为,以便始终使用特定的默认流(例如,如果IStream不能从容器中解析出来).这样做意味着我们根本不需要改变它RandomNumberGenerator:
public class NumberWriterFactory : INumberWriterFactory
{
readonly IStream stream;
readonly IContainer container;
public NumberWriterFactory(IStream stream, IContainer container)
{
this.stream = stream;
this.container = container;
}
public INumberWriter Create(int number)
{
return container.Resolve<INumberWriter>(number, this.stream);
}
public INumberWriter Create(int number, IStream stream)
{
return container.Resolve<INumberWriter>(number, stream);
}
}
Run Code Online (Sandbox Code Playgroud)
没有变化RandomNumberGenerator,但行为发生了变化:
public class RandomNumberGenerator
{
readonly INumberWriterFactory numberWriterFactory;
public RandomNumberGenerator(INumberWriterFactory numberWriterFactory)
{
this.numberWriterFactory = numberWriterFactory;
}
public void Generate()
{
Random random = new Random();
for (int i = 0; i < 10; i++)
{
// Writes to the IStream instance that the factory contains
var numberWriter = numberWriterFactory.Create(random.Next());
numberWriter.Write();
}
}
// the rest as before
}
Run Code Online (Sandbox Code Playgroud)
再次,这是在这个意义上,如果你已经在使用一个工厂接口,如一个使用的有用的AsFactory(),你可以很容易地掉出来了一个新的实现.如果您已经使用容器,那么这样做会更加困难; 找到你需要改变的地方更加困难,更换容器的使用更难以使用新的类型(即工厂).
注意:您必须创建一个INumberWriterFactoryFactory注入IStream混凝土工厂.
有很多人认为只有一个组合根,这是唯一一次允许对IOC容器的引用.这样做可以帮助您避免多种反模式,例如服务定位器模式.
请注意,这些例子很愚蠢,但我希望他们能够得到这些观点.
| 归档时间: |
|
| 查看次数: |
5931 次 |
| 最近记录: |