InjectionValueBuilder.cs
136 lines
| 4.5 KiB
| text/x-csharp
|
CSharpLexer
|
|
r274 | using System; | |
|
|
r279 | using System.Collections; | |
|
|
r277 | using System.Collections.Generic; | |
|
|
r274 | using System.ComponentModel; | |
|
|
r277 | using System.Linq; | |
|
|
r274 | using System.Xml.Serialization; | |
| using Unity.Injection; | |||
| namespace Implab.ServiceHost.Unity { | |||
|
|
r278 | public class InjectionParameterBuilder { | |
|
|
r274 | ||
| readonly TypeResolver m_resolver; | |||
| public Type DefaultType { get; private set; } | |||
|
|
r277 | public Type ValueType { get; private set; } | |
|
|
r274 | ||
|
|
r279 | object m_value; | |
|
|
r274 | ||
|
|
r279 | public object Value { | |
|
|
r274 | get { | |
|
|
r279 | if (!ValueSpecified) | |
| throw new InvalidOperationException("The regular value must be set (dependency or array are not situable in this context)"); | |||
| return m_value; | |||
| } | |||
| } | |||
| public bool ValueSpecified { get; private set; } | |||
| InjectionParameterValue m_injection; | |||
|
|
r274 | ||
|
|
r279 | public InjectionParameterValue Injection { | |
| get { | |||
| if (m_injection == null) | |||
| throw new InvalidOperationException("The injection parameter is not specified"); | |||
| return m_injection; | |||
|
|
r274 | } | |
| } | |||
|
|
r279 | public bool InjectionSpecified { | |
| get { return m_injection != null; } | |||
| } | |||
|
|
r278 | internal InjectionParameterBuilder(TypeResolver resolver, Type defaultType) { | |
|
|
r274 | m_resolver = resolver; | |
|
|
r277 | DefaultType = defaultType; | |
|
|
r274 | } | |
|
|
r277 | public Type ResolveInjectedValueType(string typeSpec) { | |
|
|
r274 | if (string.IsNullOrEmpty(typeSpec)) { | |
| if (DefaultType == null) | |||
| throw new Exception("The type must be specified"); | |||
| return DefaultType; | |||
| } | |||
|
|
r278 | return m_resolver.Resolve(typeSpec, true); | |
|
|
r274 | } | |
|
|
r277 | public Type ResolveType(string typeSpec) { | |
|
|
r279 | return string.IsNullOrEmpty(typeSpec) ? null : m_resolver.Resolve(typeSpec, true); | |
|
|
r277 | } | |
|
|
r274 | ||
|
|
r277 | public void SetValue(Type type, object value) { | |
|
|
r279 | Safe.ArgumentNotNull(type, nameof(type)); | |
|
|
r277 | ValueType = type; | |
|
|
r279 | m_value = value; | |
| ValueSpecified = true; | |||
| m_injection = new InjectionParameter(type, value); | |||
|
|
r277 | } | |
|
|
r279 | public void SetDependency(Type type, string name, bool optional) { | |
| Safe.ArgumentNotNull(type, nameof(type)); | |||
|
|
r277 | ||
| ValueType = type; | |||
|
|
r279 | ValueSpecified = false; | |
| m_value = null; | |||
| m_injection = optional ? (InjectionParameterValue)new OptionalParameter(type, name) : new ResolvedParameter(type, name); | |||
|
|
r274 | } | |
|
|
r277 | internal void Visit(ArrayParameterElement arrayParameter) { | |
| Type itemsType = null; | |||
| var arrayType = string.IsNullOrEmpty(arrayParameter.TypeName) ? null : ResolveType(arrayParameter.TypeName); | |||
|
|
r274 | ||
|
|
r279 | if (arrayType == null) | |
| arrayType = DefaultType; | |||
|
|
r277 | if (!string.IsNullOrEmpty(arrayParameter.ItemsType)) { | |
| itemsType = ResolveType(arrayParameter.ItemsType); | |||
|
|
r279 | arrayType = itemsType.MakeArrayType(); | |
|
|
r277 | } else { | |
|
|
r279 | itemsType = GetItemsType(arrayType); | |
|
|
r277 | } | |
|
|
r274 | ||
|
|
r277 | if (itemsType == null) | |
| throw new Exception("Failed to determine array elements type"); | |||
|
|
r274 | ||
|
|
r281 | InjectionParameterValue[] injections = (arrayParameter.Items ?? new AbstractInjectionParameter[0]) | |
|
|
r277 | .Select(x => { | |
|
|
r278 | var builder = new InjectionParameterBuilder(m_resolver, itemsType); | |
|
|
r277 | x.Visit(builder); | |
| return builder.Injection; | |||
| }) | |||
| .ToArray(); | |||
|
|
r278 | var array = itemsType.IsGenericParameter ? | |
|
|
r279 | (InjectionParameterValue)new GenericResolvedArrayParameter(itemsType.Name, injections) : | |
|
|
r278 | new ResolvedArrayParameter(itemsType, injections); | |
|
|
r277 | ValueType = arrayType; | |
|
|
r279 | m_value = null; | |
| ValueSpecified = false; | |||
| m_injection = array; | |||
| } | |||
| Type GetItemsType(Type collectionType) { | |||
| if (collectionType == null) | |||
| return null; | |||
| Type itemsType = null; | |||
| if (collectionType.GetGenericTypeDefinition() == typeof(IEnumerable<>)) { | |||
| itemsType = collectionType.GetGenericArguments()[0]; | |||
| } else if (collectionType == typeof(IEnumerable)) { | |||
| itemsType = typeof(object); | |||
| } else { | |||
| itemsType = collectionType.GetInterface(typeof(IEnumerable<>).FullName)?.GetGenericArguments()[0]; | |||
| } | |||
| return itemsType; | |||
|
|
r274 | } | |
| } | |||
| } |
