using System; using System.Collections.Generic; using System.Reflection; using Implab.Components; using Unity; using Unity.Injection; using Unity.Lifetime; namespace Implab.ServiceHost.Unity { public class FactoryActivator : ITypeRegistration { class FactoryInjector : ITypeMemberInjection { public InjectionFactory Factory { get; set; } public void Visit(TypeRegistrationBuilder builder) { builder.AddInjectionMember(Factory); } } public Type FactoryType { get; set; } public string FactoryName { get; set; } public Type RegistrationType { get; set; } public LifetimeManager Lifetime { get; set; } public IEnumerable MemberInjections { get { if (RegistrationType == null) throw new Exception($"RegistrationType must be specified"); if (!typeof(IFactory<>).MakeGenericType(RegistrationType).IsAssignableFrom(FactoryType)) throw new Exception($"The factory {FactoryType} can't be used to create {RegistrationType} instances"); if (FactoryType.ContainsGenericParameters) { yield return new FactoryInjector { Factory = CreateDynamicInjectionFactory(FactoryName) }; } else { yield return new FactoryInjector { Factory = (InjectionFactory)GetType() .GetMethod(nameof(CreateInjectionFactory), BindingFlags.Static | BindingFlags.NonPublic) .MakeGenericMethod(FactoryType, RegistrationType) .Invoke(null, new [] { FactoryName }) }; } } } public string Name { get; set; } public Type GetRegistrationType(ContainerBuilder builder) { return RegistrationType; } public LifetimeManager GetLifetime(ContainerBuilder builder) { return Lifetime; } public Type GetImplementationType(ContainerBuilder builder) { return null; } /// /// Указывает зависимость, реализующую интерфейс , /// которая будет использоваться в качестве фабрики для создания объектов /// /// static InjectionFactory CreateInjectionFactory(string dependencyName) where TFac : IFactory { return new InjectionFactory(c => c.Resolve(dependencyName).Create()); } static InjectionFactory CreateDynamicInjectionFactory(string dependencyName) { return new InjectionFactory((c,t,name) => ((IFactory)c.Resolve(t, dependencyName)).Create()); } } }