|
|
using System;
|
|
|
using System.Xml.Serialization;
|
|
|
using Implab.Components;
|
|
|
|
|
|
namespace Implab.ServiceHost.Unity {
|
|
|
/// <summary>
|
|
|
/// Расширяет стандартную регистрацию типа до фабрики, вместе с регистрацией
|
|
|
/// самой фабрики создаются регистрации сервисов, которые она предоставляет.
|
|
|
/// </summary>
|
|
|
public class FactoryElement : RegisterElement {
|
|
|
|
|
|
/// <summary>
|
|
|
/// Записи о сервисах, которые создаются данной фабрикой.
|
|
|
/// </summary>
|
|
|
/// <remarks>
|
|
|
/// Сервисы, которые указаны в регистарциях они должны соответсвовать тому,
|
|
|
/// что фабрика возвращает, но это остается на откуп контейнера
|
|
|
/// </remarks>
|
|
|
[XmlElement("provides")]
|
|
|
public ProvidesElement[] Provides { get; set; }
|
|
|
|
|
|
/// <summary>
|
|
|
/// Переопределяет стандарное поведение регистрации типа в контейнере,
|
|
|
/// дополняя его регистрацией фабричных методов для получения типов.
|
|
|
/// </summary>
|
|
|
/// <param name="builder">Объект для конфигурирования контейнера.</param>
|
|
|
public override void Visit(ContainerBuilder builder) {
|
|
|
var factoryType = GetRegistrationType(builder.ResolveType);
|
|
|
|
|
|
base.Visit(builder);
|
|
|
|
|
|
if (Provides != null && Provides.Length > 0) {
|
|
|
// если регистрации явно заданы, используеися информация из них
|
|
|
foreach(var item in Provides) {
|
|
|
var activator = new FactoryActivator {
|
|
|
Name = item.RegistrationName,
|
|
|
RegistrationType = builder.ResolveType(item.RegistrationType),
|
|
|
FactoryName = Name,
|
|
|
FactoryType = factoryType
|
|
|
};
|
|
|
activator.Visit(builder);
|
|
|
}
|
|
|
} else {
|
|
|
// если регистрация явно не задана, в качестве сервиса для регистрации
|
|
|
// используется тип создаваемый фабрикой, который будет добавлен в контейнер
|
|
|
// с темже именем, что и сама фабрика (разные типы могут иметь одно имя для регистрации)
|
|
|
var providedType = (
|
|
|
factoryType.IsGenericType && factoryType.GetGenericTypeDefinition() == typeof(IFactory<>) ?
|
|
|
factoryType :
|
|
|
factoryType.GetInterface(typeof(IFactory<>).FullName)
|
|
|
)?
|
|
|
.GetGenericArguments()[0];
|
|
|
|
|
|
// не удалось определеить тип
|
|
|
if (providedType == null)
|
|
|
throw new ArgumentException("Failed to determine a type provided by the factory");
|
|
|
|
|
|
if (providedType.IsGenericParameter)
|
|
|
throw new ArgumentException("Can't register a generic type paramter as a service");
|
|
|
|
|
|
var activator = new FactoryActivator {
|
|
|
Name = Name,
|
|
|
RegistrationType = providedType,
|
|
|
FactoryName = Name,
|
|
|
FactoryType = factoryType
|
|
|
};
|
|
|
|
|
|
activator.Visit(builder);
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
}
|