using System; using System.Reflection; using Unity; namespace Implab.ServiceHost.Unity { public class ContainerBuilder { readonly TypeResolver m_resolver; readonly UnityContainer m_container; readonly ContainerConfigurationSchema m_schema; public UnityContainer Container { get { return m_container; } } public ContainerBuilder() : this(null, null) { } public ContainerBuilder(UnityContainer container, ContainerConfigurationSchema schema) { m_container = container ?? new UnityContainer(); m_resolver = new TypeResolver(); m_schema = schema ?? ContainerConfigurationSchema.Default; } public Type ResolveType(string typeReference) { return m_resolver.Resolve(typeReference, true); } internal void Visit(TypeAbstractRegistration typeRegistration) { var registrationType = typeRegistration.GetRegistrationType(ResolveType); var implementationType = typeRegistration.GetImplementationType(ResolveType) ?? registrationType; var registrationContext = new TypeRegistrationBuilder( m_resolver, registrationType, implementationType ); typeRegistration.Visit(registrationContext); m_container.RegisterType( registrationContext.RegistrationType, registrationContext.ImplementationType, typeRegistration.Name, registrationContext.Lifetime, registrationContext.Injections ); } internal void Visit(InstanceAbstractRegistration instanceRegistration) { var registrationType = instanceRegistration.GetRegistrationType(ResolveType); var builder = new InstanceRegistrationBuilder(m_resolver, registrationType); instanceRegistration.Visit(builder); m_container.RegisterInstance( builder.ValueBuilder.ValueType, instanceRegistration.Name, builder.ValueBuilder.Value, builder.Lifetime ); } internal void Visit(FactoryAbstractRegistratrion factoryRgistration) { var registrationType = factoryRgistration.GetRegistrationType(ResolveType); var builder = new FactoryRegistrationBuilder(registrationType); factoryRgistration.Visit(builder); m_container.RegisterType( builder.RegistrationType, factoryRgistration.Name, builder.Lifetime, builder.Factory ); } public void Visit(ITypeRegistration registration) { Safe.ArgumentNotNull(registration, nameof(registration)); var registrationType = registration.GetRegistrationType(this); var implementationType = registration.GetImplementationType(this) ?? registrationType; if (registrationType == null) throw new Exception($"A type must be specified for the registration {registration.Name}"); var builder = new TypeRegistrationBuilder( m_resolver, registrationType, implementationType ); builder.Lifetime = registration.GetLifetime(this); if (registration.MemberInjections != null) { foreach(var member in registration.MemberInjections) member.Visit(builder); } m_container.RegisterType( builder.RegistrationType, builder.ImplementationType, registration.Name, builder.Lifetime, builder.Injections ); } public void Visit(IInstanceRegistration registration) { Safe.ArgumentNotNull(registration, nameof(registration)); var registrationType = registration.GetRegistrationType(this); var builder = new InstanceRegistrationBuilder ( m_resolver, registrationType ); builder.Lifetime = registration.GetLifetime(this); if (registration.MemberInjections != null) { foreach(var member in registration.MemberInjections) member.Visit(builder.ValueBuilder); } if (builder.RegistrationType == null && builder.ValueBuilder.ValueType == null) throw new Exception($"A type must be specified for the registration {registration.Name}"); m_container.RegisterInstance( builder.RegistrationType ?? builder.ValueBuilder.ValueType, registration.Name, builder.ValueBuilder.Injection, builder.Lifetime ); } public void Visit(IFactoryRegistration registration) { Safe.ArgumentNotNull(registration, nameof(registration)); var registrationType = registration.GetRegistrationType(this); var builder = new FactoryRegistrationBuilder(registrationType); if (registration.MemberInjections != null) { foreach(var member in registration.MemberInjections) member?.Visit(builder); } } public void AddNamespace(string ns) { m_resolver.AddNamespace(ns); } public void AddAssembly(string assembly) { } public void Include(string file) { var includeContext = new ContainerBuilder(m_container, m_schema); includeContext.LoadConfig(file); } public void LoadConfig(string file) { var config = m_schema.LoadFile(file); config.Visit(this); } } }