FactoryElement.cs
72 lines
| 3.8 KiB
| text/x-csharp
|
CSharpLexer
cin
|
r278 | using System; | |
using System.Xml.Serialization; | |||
using Implab.Components; | |||
namespace Implab.ServiceHost.Unity { | |||
/// <summary> | |||
/// Расширяет стандартную регистрацию типа до фабрики, вместе с регистрацией | |||
/// самой фабрики создаются регистрации сервисов, которые она предоставляет. | |||
/// </summary> | |||
cin
|
r279 | public class FactoryElement : RegisterElement, ITypeRegistration { | |
cin
|
r278 | ||
/// <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, | |||
cin
|
r281 | FactoryType = factoryType, | |
Lifetime = item.Lifetime.GetLifetime(builder) | |||
cin
|
r278 | }; | |
cin
|
r279 | builder.Visit(activator); | |
cin
|
r278 | } | |
} 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 | |||
}; | |||
cin
|
r279 | builder.Visit(activator); | |
cin
|
r278 | } | |
} | |||
} | |||
} |