using System; using System.IO; using System.Reflection; using Implab.Diagnostics; using Unity; namespace Implab.ServiceHost.Unity { using Log = Trace; public class ContainerBuilder { readonly TypeResolver m_resolver; readonly IUnityContainer m_container; readonly ContainerConfigurationSchema m_schema; Uri m_location; public IUnityContainer Container { get { return m_container; } } public ContainerBuilder() : this(null, null) { } public ContainerBuilder(IUnityContainer container, ContainerConfigurationSchema schema) { m_container = container ?? new UnityContainer(); m_resolver = new TypeResolver(); m_schema = schema ?? ContainerConfigurationSchema.Default; } public Type ResolveType(string typeReference) { var resolved = string.IsNullOrEmpty(typeReference) ? null : m_resolver.Resolve(typeReference, true); Log.Debug("ResolveType('{0}'): {1}", typeReference, resolved?.FullName); return resolved; } 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.Value, builder.Lifetime ); } public void AddNamespace(string ns) { m_resolver.AddNamespace(ns); } public void AddAssembly(string assembly) { } /// /// Includes the confguration. Creates a new , /// and loads the configuration to it. The created builder will share the /// container and will have its own isolated type resolver. /// /// A path to configuration relative to the current configuration. public void Include(string file) { var includeContext = new ContainerBuilder(m_container, m_schema); if (m_location != null) { var uri = new Uri(m_location, file); includeContext.LoadConfig(uri); } else { includeContext.LoadConfig(file); } } /// /// Loads a configuration from the specified local file. /// /// The path to the configuration file. public void LoadConfig(string file) { Safe.ArgumentNotEmpty(file, nameof(file)); LoadConfig(new Uri(Path.GetFullPath(file))); } public void LoadConfig(Uri location) { Safe.ArgumentNotNull(location, nameof(location)); m_location = location; var config = m_schema.LoadConfig(location.ToString()); config.Visit(this); } } }