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