|
|
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; }
|
|
|
|
|
|
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) {
|
|
|
m_resolver = resolver;
|
|
|
DefaultType = defaultType;
|
|
|
}
|
|
|
|
|
|
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 ? (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 InjectionParameterElement[0])
|
|
|
.Select(x => {
|
|
|
var builder = new InjectionParameterBuilder(m_resolver, itemsType);
|
|
|
x.Visit(builder);
|
|
|
return builder.Injection;
|
|
|
})
|
|
|
.ToArray();
|
|
|
|
|
|
var array = itemsType.IsGenericParameter ?
|
|
|
(InjectionParameterValue)new GenericResolvedArrayParameter(itemsType.Name, injections) :
|
|
|
new ResolvedArrayParameter(itemsType, injections);
|
|
|
|
|
|
ValueType = arrayType;
|
|
|
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;
|
|
|
}
|
|
|
}
|
|
|
}
|