using System; using System.Xml.Serialization; using Implab.Components; namespace Implab.ServiceHost.Unity { /// /// Расширяет стандартную регистрацию типа до фабрики, вместе с регистрацией /// самой фабрики создаются регистрации сервисов, которые она предоставляет. /// public class FactoryElement : RegisterElement, ITypeRegistration { /// /// Записи о сервисах, которые создаются данной фабрикой. /// /// /// Сервисы, которые указаны в регистарциях они должны соответсвовать тому, /// что фабрика возвращает, но это остается на откуп контейнера /// [XmlElement("provides")] public ProvidesElement[] Provides { get; set; } /// /// Переопределяет стандарное поведение регистрации типа в контейнере, /// дополняя его регистрацией фабричных методов для получения типов. /// /// Объект для конфигурирования контейнера. 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 }; builder.Visit(activator); } } 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 }; builder.Visit(activator); } } } }