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