Рассмотрим пример кода:
namespace Test
{
using System;
public class TestMain
{
public static void Main(string[] args)
{
StructureMap.ObjectFactory.Configure(x =>
{
x.For< IConnection >().Use< Connection >();
x.For< IReceiver >().Use< Receiver >();
});
IReceiver receiver = StructureMap.ObjectFactory.GetInstance< IReceiver >();
receiver.StartListening();
receiver.StopListening();
}
}
public interface IReceiver
{
void StartListening();
void StopListening();
}
public interface IConnection
{
void Open();
void Close();
}
public class Receiver : IReceiver
{
private IConnection connection;
public Receiver(IConnection connection)
{
Console.WriteLine("Receiver.ctor is called");
this.connection = connection;
}
public void StartListening()
{
Console.WriteLine("Receiver.StartListening is called");
this.connection.Open();
}
public void StopListening()
{
Console.WriteLine("Receiver.StopListening is called");
this.connection.Close();
}
}
public class Connection : IConnection
{
private Guid code;
public Connection()
{
Console.WriteLine("Connection.ctor is called");
code = Guid.NewGuid();
}
public void Open()
{
Console.WriteLine("Connection.Open is called");
Console.WriteLine("Connection \"{0}\" is opened", this.code);
}
public void Close()
{
Console.WriteLine("Connection.Close is called");
Console.WriteLine("Connection \"{0}\" is closed", this.code);
}
}
}
Код довольно простой и вряд ли нуждается в детальном пояснении. У нас есть 2 класса, один использует другой и оба реализуют свои интерфейсы.
При таком описании, вызов конструктора Connection произойдет до вызова конструктора Receiver. Более того, если бы Connection зависел бы от других объектов, то и их конструкторы были бы вызваны. Т.е. все дерево объектов было бы создано в памяти, лишь для того, чтобы передать Connection в Receiver.
В StructureMap появилась фича Lazy загрузки таких зависимостей. Для этого достаточно переписать объявление конструктора Receiver следующим образом:
public class Receiver : IReceiver
{
private Func< IConnection > connection;
public Receiver(Func< IConnection > connection)
{
Console.WriteLine("Receiver.ctor is called");
this.connection = connection;
}
public void StartListening()
{
Console.WriteLine("Receiver.StartListening is called");
this.connection().Open();
}
public void StopListening()
{
Console.WriteLine("Receiver.StopListening is called");
this.connection().Close();
}
}
Код биндинга StructureMap при этом не меняется.
Посмотрим на результат выполнения кода:
Из результатов видно, что вызов конструктора Connection происходит в методе Receiver.StartListening. Т.е. именно с этого момента мы создаем все дерево объектов. В результатах виден еще один важный момент: при вызове Func
Вот и все, что я хотел сегодня рассказать. Надеюсь, что кое-кому из моих читателей теперь не придется вызывать Factory.GetInstance< T > напрямую в коде, для того чтобы управлять временем жизни объектов ;)

Комментариев нет:
Отправить комментарий