using System; using System.Collections.Generic; using System.ComponentModel; using System.Linq; using System.Xml.Serialization; using Implab.Xml; using Unity.Injection; using Unity.Registration; namespace Implab.ServiceHost.Unity { class RegistrationContext { readonly TypeResolver m_resolver; List m_injections = new List(); Type m_defaultType; public Type RegistrationType { get; private set; } public Type ImplementationType { get; private set; } public RegistrationContext(TypeResolver resolver, string typeSpec, string implSpec) { RegistrationType = resolver.Resolve(string.IsNullOrEmpty(typeSpec) ? implSpec : typeSpec); ImplementationType = string.IsNullOrEmpty(implSpec) ? RegistrationType : resolver.Resolve(implSpec); if (RegistrationType.IsGenericTypeDefinition) { m_resolver = new TypeResolver(resolver); foreach (var p in ImplementationType.GetGenericArguments()) m_resolver.AddMapping(p.Name, p); } else { m_resolver = resolver; } } public InjectionMember[] Injections { get { return m_injections.ToArray(); } } public void Visit(ConstructorInjectionElement constructorInjection) { var parameters = constructorInjection.Parameters?.Select(x => x.Resolve(this)).ToArray(); var injection = parameters != null ? new InjectionConstructor(parameters) : new InjectionConstructor(); m_injections.Add(injection); } public void Visit(MethodInjectionElement methodInjection) { var parameters = methodInjection.Parameters?.Select(x => x.Resolve(this)).ToArray(); var injection = parameters != null ? new InjectionMethod(methodInjection.Name, parameters) : new InjectionMethod(methodInjection.Name); m_injections.Add(injection); } public void Visit(PropertyInjectionElement propertyInjection) { if (propertyInjection.Value == null) throw new Exception($"A value value must be specified for the property '{propertyInjection.Name}'"); try { m_defaultType = RegistrationType.GetProperty(propertyInjection.Name)?.PropertyType; var parameter = propertyInjection.Value.Resolve(this); var injection = new InjectionProperty(propertyInjection.Name, parameter); m_injections.Add(injection); } finally { m_defaultType = null; } } Type ResolveParameterType(InjectionParameterElement injectionParameter) { if (string.IsNullOrEmpty(injectionParameter.TypeName)) { if (m_defaultType == null) throw new Exception($"A type must be specified for the parameter {injectionParameter}"); return m_defaultType; } return m_resolver.Resolve(injectionParameter.TypeName); } public object Resolve(DefaultParameterElement defaultParameter) { var type = ResolveParameterType(defaultParameter); return Safe.CreateDefaultValue(type); } public object Resolve(ValueParameterElement valueParameter) { var type = ResolveParameterType(valueParameter); return TypeDescriptor.GetConverter(type).ConvertFromString(valueParameter.Value); } public object Resolve(SerializedParameterElement serializedParameter) { var type = ResolveParameterType(serializedParameter); if (serializedParameter.Content == null || serializedParameter.Content.Length == 0) return Safe.CreateDefaultValue(type); var serializer = new XmlSerializer(type); using (var reader = serializedParameter.Content[0].CreateNavigator().ReadSubtree()) return serializer.Deserialize(reader); } public InjectionParameterValue Resolve(DependencyParameterElement dependencyParameter) { var type = ResolveParameterType(dependencyParameter); return new ResolvedParameter(type, dependencyParameter.DependencyName); } } }