comparison Implab.ServiceHost/Unity/FactoryElement.cs @ 278:6691aff01de1 v3

Implab: added XmlDefaultSeializer (SerializersPool is now obsolete) Implab.ServiceHost: rewritten TypeReference (added support for nested types), stable API
author cin
date Thu, 03 May 2018 09:59:44 +0300
parents
children 8714471e8d78
comparison
equal deleted inserted replaced
277:963b17c275be 278:6691aff01de1
1 using System;
2 using System.Xml.Serialization;
3 using Implab.Components;
4
5 namespace Implab.ServiceHost.Unity {
6 /// <summary>
7 /// Расширяет стандартную регистрацию типа до фабрики, вместе с регистрацией
8 /// самой фабрики создаются регистрации сервисов, которые она предоставляет.
9 /// </summary>
10 public class FactoryElement : RegisterElement {
11
12 /// <summary>
13 /// Записи о сервисах, которые создаются данной фабрикой.
14 /// </summary>
15 /// <remarks>
16 /// Сервисы, которые указаны в регистарциях они должны соответсвовать тому,
17 /// что фабрика возвращает, но это остается на откуп контейнера
18 /// </remarks>
19 [XmlElement("provides")]
20 public ProvidesElement[] Provides { get; set; }
21
22 /// <summary>
23 /// Переопределяет стандарное поведение регистрации типа в контейнере,
24 /// дополняя его регистрацией фабричных методов для получения типов.
25 /// </summary>
26 /// <param name="builder">Объект для конфигурирования контейнера.</param>
27 public override void Visit(ContainerBuilder builder) {
28 var factoryType = GetRegistrationType(builder.ResolveType);
29
30 base.Visit(builder);
31
32 if (Provides != null && Provides.Length > 0) {
33 // если регистрации явно заданы, используеися информация из них
34 foreach(var item in Provides) {
35 var activator = new FactoryActivator {
36 Name = item.RegistrationName,
37 RegistrationType = builder.ResolveType(item.RegistrationType),
38 FactoryName = Name,
39 FactoryType = factoryType
40 };
41 activator.Visit(builder);
42 }
43 } else {
44 // если регистрация явно не задана, в качестве сервиса для регистрации
45 // используется тип создаваемый фабрикой, который будет добавлен в контейнер
46 // с темже именем, что и сама фабрика (разные типы могут иметь одно имя для регистрации)
47 var providedType = (
48 factoryType.IsGenericType && factoryType.GetGenericTypeDefinition() == typeof(IFactory<>) ?
49 factoryType :
50 factoryType.GetInterface(typeof(IFactory<>).FullName)
51 )?
52 .GetGenericArguments()[0];
53
54 // не удалось определеить тип
55 if (providedType == null)
56 throw new ArgumentException("Failed to determine a type provided by the factory");
57
58 if (providedType.IsGenericParameter)
59 throw new ArgumentException("Can't register a generic type paramter as a service");
60
61 var activator = new FactoryActivator {
62 Name = Name,
63 RegistrationType = providedType,
64 FactoryName = Name,
65 FactoryType = factoryType
66 };
67
68 activator.Visit(builder);
69 }
70 }
71 }
72 }