Refactoring
This commit is contained in:
Родитель
e6a55bfaf8
Коммит
71c75f5d02
|
@ -1,137 +0,0 @@
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Linq.Expressions;
|
|
||||||
using System.Reflection;
|
|
||||||
using Unity.Injection;
|
|
||||||
using Unity.Policy;
|
|
||||||
using Unity.Storage;
|
|
||||||
|
|
||||||
namespace Unity.Processors
|
|
||||||
{
|
|
||||||
public delegate Expression MemberExpressionFactory(Attribute attribute, Expression member, object info, Type type, object resolver);
|
|
||||||
|
|
||||||
public abstract partial class BuildMemberProcessor<TMemberInfo, TData> where TMemberInfo : MemberInfo
|
|
||||||
{
|
|
||||||
#region Fields
|
|
||||||
|
|
||||||
protected (Type type, MemberExpressionFactory factory)[] ExpressionFactories;
|
|
||||||
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
|
|
||||||
#region Public Methods
|
|
||||||
|
|
||||||
public void Add(Type type, MemberExpressionFactory factory)
|
|
||||||
{
|
|
||||||
for (var i = 0; i < ExpressionFactories.Length; i++)
|
|
||||||
{
|
|
||||||
if (ExpressionFactories[i].type != type) continue;
|
|
||||||
ExpressionFactories[i].factory = factory;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
var factories = new (Type type, MemberExpressionFactory factory)[ExpressionFactories.Length + 1];
|
|
||||||
Array.Copy(ExpressionFactories, factories, ExpressionFactories.Length);
|
|
||||||
factories[ExpressionFactories.Length] = (type, factory);
|
|
||||||
ExpressionFactories = factories;
|
|
||||||
}
|
|
||||||
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
|
|
||||||
#region Overrides
|
|
||||||
|
|
||||||
/// <inheritdoc />
|
|
||||||
public override IEnumerable<Expression> GetBuildSteps(Type type, IPolicySet registration)
|
|
||||||
{
|
|
||||||
var selector = GetPolicy<ISelect<TMemberInfo>>(registration);
|
|
||||||
var members = selector.Select(type, registration);
|
|
||||||
return ExpressionsFromSelected(type, members);
|
|
||||||
}
|
|
||||||
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
|
|
||||||
#region Build Expression
|
|
||||||
|
|
||||||
protected virtual IEnumerable<Expression> ExpressionsFromSelected(Type type, IEnumerable<object> members)
|
|
||||||
{
|
|
||||||
foreach (var member in members)
|
|
||||||
{
|
|
||||||
|
|
||||||
switch (member)
|
|
||||||
{
|
|
||||||
case TMemberInfo memberInfo:
|
|
||||||
yield return BuildMemberExpression(memberInfo);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case InjectionMember<TMemberInfo, TData> injectionMember:
|
|
||||||
var (info, value) = injectionMember.FromType(type);
|
|
||||||
yield return BuildMemberExpression(info, value);
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
throw new InvalidOperationException($"Unknown MemberInfo<{typeof(TMemberInfo)}> type");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
protected virtual Expression BuildMemberExpression(TMemberInfo info)
|
|
||||||
{
|
|
||||||
var member = CreateMemberExpression(info);
|
|
||||||
|
|
||||||
foreach (var pair in ExpressionFactories)
|
|
||||||
{
|
|
||||||
#if NETSTANDARD1_0 || NETCOREAPP1_0
|
|
||||||
var attribute = info.GetCustomAttributes()
|
|
||||||
.Where(a => a.GetType()
|
|
||||||
.GetTypeInfo()
|
|
||||||
.IsAssignableFrom(pair.type.GetTypeInfo()))
|
|
||||||
.FirstOrDefault();
|
|
||||||
#else
|
|
||||||
var attribute = info.GetCustomAttribute(pair.type);
|
|
||||||
#endif
|
|
||||||
if (null == attribute || null == pair.factory)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
return pair.factory(attribute, member, info, MemberType(info), null);
|
|
||||||
}
|
|
||||||
|
|
||||||
return Expression.Assign(member, GetExpression(info, null, null));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
protected virtual Expression BuildMemberExpression(TMemberInfo info, TData resolver)
|
|
||||||
=> Expression.Assign(CreateMemberExpression(info), GetExpression(info, null, resolver));
|
|
||||||
|
|
||||||
protected virtual Expression GetExpression(TMemberInfo info, string name, object resolver) => throw new NotImplementedException();
|
|
||||||
|
|
||||||
protected virtual MemberExpression CreateMemberExpression(TMemberInfo info) => throw new NotImplementedException();
|
|
||||||
|
|
||||||
protected abstract Type MemberType(TMemberInfo info);
|
|
||||||
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
|
|
||||||
#region Parameter Expression Factories
|
|
||||||
|
|
||||||
protected virtual Expression DependencyExpressionFactory(Attribute attribute, Expression member, object memberInfo, Type type, object resolver)
|
|
||||||
{
|
|
||||||
TMemberInfo info = (TMemberInfo)memberInfo;
|
|
||||||
return Expression.Assign(member, GetExpression(info, ((DependencyResolutionAttribute)attribute).Name, resolver ?? DependencyAttribute.Instance));
|
|
||||||
}
|
|
||||||
|
|
||||||
protected virtual Expression OptionalDependencyExpressionFactory(Attribute attribute, Expression member, object memberInfo, Type type, object resolver)
|
|
||||||
{
|
|
||||||
TMemberInfo info = (TMemberInfo)memberInfo;
|
|
||||||
return Expression.TryCatch(
|
|
||||||
Expression.Assign(member, GetExpression(info, ((OptionalDependencyAttribute)attribute).Name, resolver ?? OptionalDependencyAttribute.Instance)),
|
|
||||||
Expression.Catch(typeof(Exception),
|
|
||||||
Expression.Assign(member, Expression.Constant(null, type))));
|
|
||||||
}
|
|
||||||
|
|
||||||
#endregion
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,86 +0,0 @@
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Linq.Expressions;
|
|
||||||
using System.Reflection;
|
|
||||||
using Unity.Builder;
|
|
||||||
using Unity.Exceptions;
|
|
||||||
using Unity.Policy;
|
|
||||||
|
|
||||||
namespace Unity.Processors
|
|
||||||
{
|
|
||||||
public abstract class BuildMemberProcessor
|
|
||||||
{
|
|
||||||
#region Fields
|
|
||||||
|
|
||||||
protected static readonly MethodInfo StringFormat =
|
|
||||||
typeof(string).GetTypeInfo()
|
|
||||||
.DeclaredMethods
|
|
||||||
.First(m =>
|
|
||||||
{
|
|
||||||
var parameters = m.GetParameters();
|
|
||||||
return m.Name == nameof(string.Format) &&
|
|
||||||
m.GetParameters().Length == 2 &&
|
|
||||||
typeof(object) == parameters[1].ParameterType;
|
|
||||||
});
|
|
||||||
|
|
||||||
protected static readonly Expression InvalidRegistrationExpression = Expression.New(typeof(InvalidRegistrationException));
|
|
||||||
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
|
|
||||||
#region Public Methods
|
|
||||||
|
|
||||||
public abstract IEnumerable<Expression> GetBuildSteps(Type type, IPolicySet registration);
|
|
||||||
|
|
||||||
public abstract ResolveDelegate<BuilderContext> GetResolver(Type type, IPolicySet registration, ResolveDelegate<BuilderContext> seed);
|
|
||||||
|
|
||||||
#endregion
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public abstract partial class BuildMemberProcessor<TMemberInfo, TData> : BuildMemberProcessor
|
|
||||||
where TMemberInfo : MemberInfo
|
|
||||||
{
|
|
||||||
#region Fields
|
|
||||||
|
|
||||||
private readonly IPolicySet _policySet;
|
|
||||||
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
|
|
||||||
#region Constructors
|
|
||||||
|
|
||||||
protected BuildMemberProcessor(IPolicySet policySet)
|
|
||||||
{
|
|
||||||
// Add Unity attribute factories
|
|
||||||
ExpressionFactories = new (Type type, MemberExpressionFactory factory)[]
|
|
||||||
{
|
|
||||||
(typeof(DependencyAttribute), DependencyExpressionFactory),
|
|
||||||
(typeof(OptionalDependencyAttribute), OptionalDependencyExpressionFactory),
|
|
||||||
};
|
|
||||||
|
|
||||||
// Add Unity attribute factories
|
|
||||||
ResolverFactories = new (Type type, MemberResolverFactory factory)[]
|
|
||||||
{
|
|
||||||
(typeof(DependencyAttribute), DependencyResolverFactory),
|
|
||||||
(typeof(OptionalDependencyAttribute), OptionalDependencyResolverFactory),
|
|
||||||
};
|
|
||||||
|
|
||||||
_policySet = policySet;
|
|
||||||
}
|
|
||||||
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
|
|
||||||
#region Policy Retrieval
|
|
||||||
|
|
||||||
public TPolicyInterface GetPolicy<TPolicyInterface>(IPolicySet registration)
|
|
||||||
{
|
|
||||||
return (TPolicyInterface)(registration.Get(typeof(TPolicyInterface)) ??
|
|
||||||
_policySet.Get(typeof(TPolicyInterface)));
|
|
||||||
}
|
|
||||||
|
|
||||||
#endregion
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,127 +0,0 @@
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Reflection;
|
|
||||||
using Unity.Builder;
|
|
||||||
using Unity.Injection;
|
|
||||||
using Unity.Policy;
|
|
||||||
using Unity.Storage;
|
|
||||||
|
|
||||||
namespace Unity.Processors
|
|
||||||
{
|
|
||||||
public delegate ResolveDelegate<BuilderContext> MemberResolverFactory(Attribute attribute, object info, object resolver, object defaultValue);
|
|
||||||
|
|
||||||
public abstract partial class BuildMemberProcessor<TMemberInfo, TData> where TMemberInfo : MemberInfo
|
|
||||||
{
|
|
||||||
#region Fields
|
|
||||||
|
|
||||||
protected (Type type, MemberResolverFactory factory)[] ResolverFactories;
|
|
||||||
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
|
|
||||||
#region Public Methods
|
|
||||||
|
|
||||||
public void Add(Type type, MemberResolverFactory factory)
|
|
||||||
{
|
|
||||||
for (var i = 0; i < ResolverFactories.Length; i++)
|
|
||||||
{
|
|
||||||
if (ResolverFactories[i].type != type) continue;
|
|
||||||
ResolverFactories[i].factory = factory;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
var factories = new (Type type, MemberResolverFactory factory)[ResolverFactories.Length + 1];
|
|
||||||
Array.Copy(ResolverFactories, factories, ResolverFactories.Length);
|
|
||||||
factories[ResolverFactories.Length] = (type, factory);
|
|
||||||
ResolverFactories = factories;
|
|
||||||
}
|
|
||||||
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
|
|
||||||
#region Overrides
|
|
||||||
|
|
||||||
public override ResolveDelegate<BuilderContext> GetResolver(Type type, IPolicySet registration, ResolveDelegate<BuilderContext> seed)
|
|
||||||
{
|
|
||||||
var selector = GetPolicy<ISelect<TMemberInfo>>(registration);
|
|
||||||
var members = selector.Select(type, registration);
|
|
||||||
var resolvers = ResolversFromSelected(type, members).ToArray();
|
|
||||||
|
|
||||||
return (ref BuilderContext c) =>
|
|
||||||
{
|
|
||||||
if (null == (c.Existing = seed(ref c))) return null;
|
|
||||||
|
|
||||||
foreach (var resolver in resolvers) resolver(ref c);
|
|
||||||
|
|
||||||
return c.Existing;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
|
|
||||||
#region Build Resolver
|
|
||||||
|
|
||||||
protected virtual IEnumerable<ResolveDelegate<BuilderContext>> ResolversFromSelected(Type type, IEnumerable<object> members)
|
|
||||||
{
|
|
||||||
foreach (var member in members)
|
|
||||||
{
|
|
||||||
|
|
||||||
switch (member)
|
|
||||||
{
|
|
||||||
case TMemberInfo memberInfo:
|
|
||||||
yield return BuildMemberResolver(memberInfo);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case InjectionMember<TMemberInfo, TData> injectionMember:
|
|
||||||
var (info, value) = injectionMember.FromType(type);
|
|
||||||
yield return BuildMemberResolver(info, value);
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
throw new InvalidOperationException($"Unknown MemberInfo<{typeof(TMemberInfo)}> type");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
protected virtual ResolveDelegate<BuilderContext> BuildMemberResolver(TMemberInfo info)
|
|
||||||
{
|
|
||||||
foreach (var pair in ResolverFactories)
|
|
||||||
{
|
|
||||||
#if NETSTANDARD1_0 || NETCOREAPP1_0
|
|
||||||
var attribute = info.GetCustomAttributes()
|
|
||||||
.Where(a => a.GetType()
|
|
||||||
.GetTypeInfo()
|
|
||||||
.IsAssignableFrom(pair.type.GetTypeInfo()))
|
|
||||||
.FirstOrDefault();
|
|
||||||
#else
|
|
||||||
var attribute = info.GetCustomAttribute(pair.type);
|
|
||||||
#endif
|
|
||||||
if (null == attribute || null == pair.factory)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
return pair.factory(attribute, info, null, null);
|
|
||||||
}
|
|
||||||
|
|
||||||
return GetResolver(info, null);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected virtual ResolveDelegate<BuilderContext> BuildMemberResolver(TMemberInfo info, TData resolver) => GetResolver(info, resolver);
|
|
||||||
|
|
||||||
protected virtual ResolveDelegate<BuilderContext> GetResolver(TMemberInfo info, object resolver) => throw new NotImplementedException();
|
|
||||||
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
|
|
||||||
#region Parameter Resolver Factories
|
|
||||||
|
|
||||||
// Default expression factory for [Dependency] attribute
|
|
||||||
protected abstract ResolveDelegate<BuilderContext> DependencyResolverFactory(Attribute attribute, object info, object resolver, object defaultValue = null);
|
|
||||||
|
|
||||||
// Default expression factory for [OptionalDependency] attribute
|
|
||||||
protected abstract ResolveDelegate<BuilderContext> OptionalDependencyResolverFactory(Attribute attribute, object info, object resolver, object defaultValue = null);
|
|
||||||
|
|
||||||
#endregion
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -0,0 +1,107 @@
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq.Expressions;
|
||||||
|
using System.Reflection;
|
||||||
|
using Unity.Injection;
|
||||||
|
|
||||||
|
namespace Unity.Processors
|
||||||
|
{
|
||||||
|
public delegate Expression ExpressionAttributeFactory(Attribute attribute, Expression member, object info, Type type, object resolver);
|
||||||
|
|
||||||
|
public abstract partial class MemberProcessor<TMemberInfo, TData> where TMemberInfo : MemberInfo
|
||||||
|
{
|
||||||
|
#region Members Processing
|
||||||
|
|
||||||
|
protected virtual IEnumerable<Expression> ExpressionsFromSelection(Type type, IEnumerable<object> members)
|
||||||
|
{
|
||||||
|
foreach (var member in members)
|
||||||
|
{
|
||||||
|
|
||||||
|
switch (member)
|
||||||
|
{
|
||||||
|
case TMemberInfo memberInfo:
|
||||||
|
yield return ExpressionFromMemberInfo(memberInfo);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case InjectionMember<TMemberInfo, TData> injectionMember:
|
||||||
|
var (info, value) = injectionMember.FromType(type);
|
||||||
|
yield return ExpressionFromMemberInfo(info, value);
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
throw new InvalidOperationException($"Unknown MemberInfo<{typeof(TMemberInfo)}> type");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected virtual Expression ExpressionFromMemberInfo(TMemberInfo info)
|
||||||
|
{
|
||||||
|
var member = CreateMemberExpression(info);
|
||||||
|
|
||||||
|
foreach (var node in AttributeFactories)
|
||||||
|
{
|
||||||
|
var attribute = GetCustomAttribute(info, node.Type);
|
||||||
|
if (null == attribute || null == node.ExpressionFactory)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
return node.ExpressionFactory(attribute, member, info, MemberType(info), null);
|
||||||
|
}
|
||||||
|
|
||||||
|
return Expression.Assign(member, GetResolverExpression(info, null, null));
|
||||||
|
}
|
||||||
|
|
||||||
|
protected virtual Expression ExpressionFromMemberInfo(TMemberInfo info, TData resolver)
|
||||||
|
{
|
||||||
|
return Expression.Assign(CreateMemberExpression(info), GetResolverExpression(info, null, resolver));
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
|
||||||
|
#region Implementation
|
||||||
|
|
||||||
|
|
||||||
|
private Expression ExpressionFromAttribute(TMemberInfo info, object resolver)
|
||||||
|
{
|
||||||
|
var member = CreateMemberExpression(info);
|
||||||
|
|
||||||
|
foreach (var node in AttributeFactories)
|
||||||
|
{
|
||||||
|
var attribute = GetCustomAttribute(info, node.Type);
|
||||||
|
if (null == attribute || null == node.ExpressionFactory)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
return node.ExpressionFactory(attribute, member, info, MemberType(info), null);
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
protected virtual Expression GetResolverExpression(TMemberInfo info, string name, object resolver) => throw new NotImplementedException();
|
||||||
|
|
||||||
|
protected virtual MemberExpression CreateMemberExpression(TMemberInfo info) => throw new NotImplementedException();
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
|
||||||
|
#region Parameter Expression Factories
|
||||||
|
|
||||||
|
protected virtual Expression DependencyExpressionFactory(Attribute attribute, Expression member, object memberInfo, Type type, object resolver)
|
||||||
|
{
|
||||||
|
TMemberInfo info = (TMemberInfo)memberInfo;
|
||||||
|
return Expression.Assign(member, GetResolverExpression(info, ((DependencyResolutionAttribute)attribute).Name, resolver ?? DependencyAttribute.Instance));
|
||||||
|
}
|
||||||
|
|
||||||
|
protected virtual Expression OptionalDependencyExpressionFactory(Attribute attribute, Expression member, object memberInfo, Type type, object resolver)
|
||||||
|
{
|
||||||
|
TMemberInfo info = (TMemberInfo)memberInfo;
|
||||||
|
return Expression.TryCatch(
|
||||||
|
Expression.Assign(member, GetResolverExpression(info, ((OptionalDependencyAttribute)attribute).Name, resolver ?? OptionalDependencyAttribute.Instance)),
|
||||||
|
Expression.Catch(typeof(Exception),
|
||||||
|
Expression.Assign(member, Expression.Constant(null, type))));
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,259 @@
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Linq.Expressions;
|
||||||
|
using System.Reflection;
|
||||||
|
using Unity.Builder;
|
||||||
|
using Unity.Exceptions;
|
||||||
|
using Unity.Injection;
|
||||||
|
using Unity.Policy;
|
||||||
|
using Unity.Registration;
|
||||||
|
|
||||||
|
namespace Unity.Processors
|
||||||
|
{
|
||||||
|
public abstract class MemberProcessor
|
||||||
|
{
|
||||||
|
#region Fields
|
||||||
|
|
||||||
|
protected static readonly MethodInfo StringFormat =
|
||||||
|
typeof(string).GetTypeInfo()
|
||||||
|
.DeclaredMethods
|
||||||
|
.First(m =>
|
||||||
|
{
|
||||||
|
var parameters = m.GetParameters();
|
||||||
|
return m.Name == nameof(string.Format) &&
|
||||||
|
m.GetParameters().Length == 2 &&
|
||||||
|
typeof(object) == parameters[1].ParameterType;
|
||||||
|
});
|
||||||
|
|
||||||
|
protected static readonly Expression InvalidRegistrationExpression = Expression.New(typeof(InvalidRegistrationException));
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
|
||||||
|
#region Public Methods
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
///
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Call hierarchy:
|
||||||
|
/// <see cref="GetExpressions"/>
|
||||||
|
/// + <see cref="SelectMembers"/>
|
||||||
|
/// + <see cref="ExpressionsFromSelected"/>
|
||||||
|
/// + <see cref="BuildMemberExpression"/>
|
||||||
|
/// + <see cref="GetResolverExpression"/>
|
||||||
|
/// </remarks>
|
||||||
|
/// <param name="type"></param>
|
||||||
|
/// <param name="registration"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public abstract IEnumerable<Expression> GetExpressions(Type type, IPolicySet registration);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
///
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Call hierarchy:
|
||||||
|
/// <see cref="GetResolver"/>
|
||||||
|
/// + <see cref="SelectMembers"/>
|
||||||
|
/// + <see cref="ResolversFromSelected"/>
|
||||||
|
/// + <see cref="BuildMemberResolver"/>
|
||||||
|
/// + <see cref="GetResolverDelegate"/>
|
||||||
|
/// </remarks>
|
||||||
|
/// <param name="type"></param>
|
||||||
|
/// <param name="registration"></param>
|
||||||
|
/// <param name="seed"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public abstract ResolveDelegate<BuilderContext> GetResolver(Type type, IPolicySet registration, ResolveDelegate<BuilderContext> seed);
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public abstract partial class MemberProcessor<TMemberInfo, TData> : MemberProcessor,
|
||||||
|
ISelect<TMemberInfo>
|
||||||
|
where TMemberInfo : MemberInfo
|
||||||
|
{
|
||||||
|
#region Fields
|
||||||
|
|
||||||
|
private readonly IPolicySet _policySet;
|
||||||
|
protected AttributeFactoryNode[] AttributeFactories;
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
|
||||||
|
#region Constructors
|
||||||
|
|
||||||
|
protected MemberProcessor(IPolicySet policySet)
|
||||||
|
{
|
||||||
|
// Add Unity attribute factories
|
||||||
|
AttributeFactories = new[]
|
||||||
|
{
|
||||||
|
new AttributeFactoryNode(typeof(DependencyAttribute),
|
||||||
|
DependencyExpressionFactory,
|
||||||
|
DependencyResolverFactory),
|
||||||
|
|
||||||
|
new AttributeFactoryNode(typeof(OptionalDependencyAttribute),
|
||||||
|
OptionalDependencyExpressionFactory,
|
||||||
|
OptionalDependencyResolverFactory),
|
||||||
|
};
|
||||||
|
|
||||||
|
_policySet = policySet;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
|
||||||
|
#region Public Methods
|
||||||
|
|
||||||
|
public void Add(Type type, ExpressionAttributeFactory expressionFactory,
|
||||||
|
ResolutionAttributeFactory resolutionFactory)
|
||||||
|
{
|
||||||
|
for (var i = 0; i < AttributeFactories.Length; i++)
|
||||||
|
{
|
||||||
|
if (AttributeFactories[i].Type != type) continue;
|
||||||
|
|
||||||
|
AttributeFactories[i].ExpressionFactory = expressionFactory;
|
||||||
|
AttributeFactories[i].ResolutionFactory = resolutionFactory;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var factories = new AttributeFactoryNode[AttributeFactories.Length + 1];
|
||||||
|
Array.Copy(AttributeFactories, factories, AttributeFactories.Length);
|
||||||
|
factories[AttributeFactories.Length] = new AttributeFactoryNode(type, expressionFactory, resolutionFactory);
|
||||||
|
AttributeFactories = factories;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
|
||||||
|
#region MemberProcessor
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override IEnumerable<Expression> GetExpressions(Type type, IPolicySet registration)
|
||||||
|
{
|
||||||
|
var selector = GetPolicy<ISelect<TMemberInfo>>(registration);
|
||||||
|
var members = selector.Select(type, registration);
|
||||||
|
|
||||||
|
return ExpressionsFromSelection(type, members);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override ResolveDelegate<BuilderContext> GetResolver(Type type, IPolicySet registration, ResolveDelegate<BuilderContext> seed)
|
||||||
|
{
|
||||||
|
var selector = GetPolicy<ISelect<TMemberInfo>>(registration);
|
||||||
|
var members = selector.Select(type, registration);
|
||||||
|
var resolvers = ResolversFromSelection(type, members).ToArray();
|
||||||
|
|
||||||
|
return (ref BuilderContext c) =>
|
||||||
|
{
|
||||||
|
if (null == (c.Existing = seed(ref c))) return null;
|
||||||
|
foreach (var resolver in resolvers) resolver(ref c);
|
||||||
|
return c.Existing;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
|
||||||
|
#region ISelect
|
||||||
|
|
||||||
|
public virtual IEnumerable<object> Select(Type type, IPolicySet registration)
|
||||||
|
{
|
||||||
|
HashSet<object> memberSet = new HashSet<object>();
|
||||||
|
|
||||||
|
// Select Injected Members
|
||||||
|
if (null != ((InternalRegistration)registration).InjectionMembers)
|
||||||
|
{
|
||||||
|
foreach (var injectionMember in ((InternalRegistration)registration).InjectionMembers)
|
||||||
|
{
|
||||||
|
if (injectionMember is InjectionMember<TMemberInfo, TData> && memberSet.Add(injectionMember))
|
||||||
|
yield return injectionMember;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Select Attributed members
|
||||||
|
IEnumerable<TMemberInfo> members = DeclaredMembers(type);
|
||||||
|
|
||||||
|
if (null == members) yield break;
|
||||||
|
foreach (var member in members)
|
||||||
|
{
|
||||||
|
for (var i = 0; i < AttributeFactories.Length; i++)
|
||||||
|
{
|
||||||
|
if (!member.IsDefined(AttributeFactories[i].Type) ||
|
||||||
|
!memberSet.Add(member)) continue;
|
||||||
|
|
||||||
|
yield return member;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
|
||||||
|
#region Implementation
|
||||||
|
|
||||||
|
protected abstract Type MemberType(TMemberInfo info);
|
||||||
|
|
||||||
|
protected abstract IEnumerable<TMemberInfo> DeclaredMembers(Type type);
|
||||||
|
|
||||||
|
protected virtual object PreProcessResolver(TMemberInfo info, object resolver)
|
||||||
|
{
|
||||||
|
switch (resolver)
|
||||||
|
{
|
||||||
|
case IResolve policy:
|
||||||
|
return (ResolveDelegate<BuilderContext>)policy.Resolve;
|
||||||
|
|
||||||
|
case IResolverFactory factory:
|
||||||
|
return factory.GetResolver<BuilderContext>(MemberType(info));
|
||||||
|
|
||||||
|
case Type type:
|
||||||
|
return typeof(Type) == MemberType(info)
|
||||||
|
? type : (object)info;
|
||||||
|
}
|
||||||
|
|
||||||
|
return resolver;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected Attribute GetCustomAttribute(TMemberInfo info, Type type)
|
||||||
|
{
|
||||||
|
#if NETSTANDARD1_0 || NETCOREAPP1_0
|
||||||
|
return info.GetCustomAttributes()
|
||||||
|
.Where(a => a.GetType()
|
||||||
|
.GetTypeInfo()
|
||||||
|
.IsAssignableFrom(type.GetTypeInfo()))
|
||||||
|
.FirstOrDefault();
|
||||||
|
#else
|
||||||
|
return info.GetCustomAttribute(type);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
public TPolicyInterface GetPolicy<TPolicyInterface>(IPolicySet registration)
|
||||||
|
{
|
||||||
|
return (TPolicyInterface)(registration.Get(typeof(TPolicyInterface)) ??
|
||||||
|
_policySet.Get(typeof(TPolicyInterface)));
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
|
||||||
|
#region Nested Types
|
||||||
|
|
||||||
|
public struct AttributeFactoryNode
|
||||||
|
{
|
||||||
|
public readonly Type Type;
|
||||||
|
public ExpressionAttributeFactory ExpressionFactory;
|
||||||
|
public ResolutionAttributeFactory ResolutionFactory;
|
||||||
|
|
||||||
|
public AttributeFactoryNode(Type type, ExpressionAttributeFactory expressionFactory, ResolutionAttributeFactory resolutionFactory)
|
||||||
|
{
|
||||||
|
Type = type;
|
||||||
|
ExpressionFactory = expressionFactory;
|
||||||
|
ResolutionFactory = resolutionFactory;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,136 @@
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Reflection;
|
||||||
|
using Unity.Builder;
|
||||||
|
using Unity.Injection;
|
||||||
|
using Unity.Policy;
|
||||||
|
|
||||||
|
namespace Unity.Processors
|
||||||
|
{
|
||||||
|
public delegate ResolveDelegate<BuilderContext> ResolutionAttributeFactory(Attribute attribute, object info, object resolver, object defaultValue);
|
||||||
|
|
||||||
|
public abstract partial class MemberProcessor<TMemberInfo, TData> where TMemberInfo : MemberInfo
|
||||||
|
{
|
||||||
|
#region Member Processing
|
||||||
|
|
||||||
|
protected virtual IEnumerable<ResolveDelegate<BuilderContext>> ResolversFromSelection(Type type, IEnumerable<object> members)
|
||||||
|
{
|
||||||
|
foreach (var member in members)
|
||||||
|
{
|
||||||
|
switch (member)
|
||||||
|
{
|
||||||
|
case TMemberInfo memberInfo:
|
||||||
|
yield return ResolverFromMemberInfo(memberInfo);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case InjectionMember<TMemberInfo, TData> injectionMember:
|
||||||
|
var (info, value) = injectionMember.FromType(type);
|
||||||
|
yield return ResolverFromMemberInfo(info, value);
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
throw new InvalidOperationException($"Unknown MemberInfo<{typeof(TMemberInfo)}> type");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
protected virtual ResolveDelegate<BuilderContext> ResolverFromMemberInfo(TMemberInfo info)
|
||||||
|
{
|
||||||
|
return GetAttributeResolver(info, DependencyAttribute.Instance) ??
|
||||||
|
GetResolverDelegate(info, DependencyAttribute.Instance);
|
||||||
|
}
|
||||||
|
|
||||||
|
TData GetParameterResolver(TMemberInfo info, object data)
|
||||||
|
{
|
||||||
|
throw new NotImplementedException();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected virtual ResolveDelegate<BuilderContext> ResolverFromMemberInfo(TMemberInfo info, TData resolver)
|
||||||
|
{
|
||||||
|
return GetResolverDelegate(info, resolver);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
|
||||||
|
#region Implementation
|
||||||
|
|
||||||
|
|
||||||
|
protected virtual ResolveDelegate<BuilderContext> GetDataResolver(TMemberInfo info, object resolver)
|
||||||
|
{
|
||||||
|
switch (resolver)
|
||||||
|
{
|
||||||
|
case DependencyAttribute dependencyAttribute:
|
||||||
|
return (ref BuilderContext context) => context.Resolve(MemberType(info), dependencyAttribute.Name);
|
||||||
|
|
||||||
|
case OptionalDependencyAttribute optionalAttribute:
|
||||||
|
return (ref BuilderContext context) =>
|
||||||
|
{
|
||||||
|
try { return context.Resolve(MemberType(info), optionalAttribute.Name); }
|
||||||
|
catch { return null; }
|
||||||
|
};
|
||||||
|
|
||||||
|
case IResolve policy:
|
||||||
|
return policy.Resolve;
|
||||||
|
|
||||||
|
case IResolverFactory<TMemberInfo> memberFactory:
|
||||||
|
return memberFactory.GetResolver<BuilderContext>(info);
|
||||||
|
|
||||||
|
case IResolverFactory typeFactory:
|
||||||
|
return typeFactory.GetResolver<BuilderContext>(MemberType(info));
|
||||||
|
|
||||||
|
case Type type:
|
||||||
|
return (ref BuilderContext context) => typeof(Type) == MemberType(info)
|
||||||
|
? type : context.Resolve(type, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
return (ref BuilderContext context) => resolver;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private ResolveDelegate<BuilderContext> GetAttributeResolver(TMemberInfo info, object resolver)
|
||||||
|
{
|
||||||
|
foreach (var node in AttributeFactories)
|
||||||
|
{
|
||||||
|
var attribute = GetCustomAttribute(info, node.Type);
|
||||||
|
if (null == attribute || null == node.ResolutionFactory)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
return node.ResolutionFactory(attribute, info, resolver, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
protected virtual ResolveDelegate<BuilderContext> GetResolverDelegate(TMemberInfo info, object resolver)
|
||||||
|
{
|
||||||
|
switch(resolver)
|
||||||
|
{
|
||||||
|
case DependencyAttribute dependencyAttribute
|
||||||
|
when ReferenceEquals(dependencyAttribute, DependencyAttribute.Instance):
|
||||||
|
break;
|
||||||
|
|
||||||
|
case OptionalDependencyAttribute optionalAttribute
|
||||||
|
when ReferenceEquals(optionalAttribute, OptionalDependencyAttribute.Instance):
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
throw new NotImplementedException();
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
|
||||||
|
#region Parameter Resolver Factories
|
||||||
|
|
||||||
|
// Default expression factory for [Dependency] attribute
|
||||||
|
protected abstract ResolveDelegate<BuilderContext> DependencyResolverFactory(Attribute attribute, object info, object resolver, object defaultValue = null);
|
||||||
|
|
||||||
|
// Default expression factory for [OptionalDependency] attribute
|
||||||
|
protected abstract ResolveDelegate<BuilderContext> OptionalDependencyResolverFactory(Attribute attribute, object info, object resolver, object defaultValue = null);
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,322 +0,0 @@
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Linq.Expressions;
|
|
||||||
using System.Reflection;
|
|
||||||
using Unity.Builder;
|
|
||||||
using Unity.Injection;
|
|
||||||
using Unity.Policy;
|
|
||||||
using Unity.Storage;
|
|
||||||
|
|
||||||
namespace Unity.Processors
|
|
||||||
{
|
|
||||||
public abstract class MethodBaseInfoProcessor<TMemberInfo> : BuildMemberProcessor<TMemberInfo, object[]>
|
|
||||||
where TMemberInfo : MethodBase
|
|
||||||
{
|
|
||||||
#region Fields
|
|
||||||
|
|
||||||
private readonly MethodInfo ResolveParameter =
|
|
||||||
typeof(BuilderContext).GetTypeInfo()
|
|
||||||
.GetDeclaredMethods(nameof(BuilderContext.Resolve))
|
|
||||||
.First(m =>
|
|
||||||
{
|
|
||||||
var parameters = m.GetParameters();
|
|
||||||
return 2 <= parameters.Length &&
|
|
||||||
typeof(ParameterInfo) == parameters[0].ParameterType;
|
|
||||||
});
|
|
||||||
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
|
|
||||||
#region Constructors
|
|
||||||
|
|
||||||
protected MethodBaseInfoProcessor(IPolicySet policySet, Type attribute)
|
|
||||||
: base(policySet)
|
|
||||||
{
|
|
||||||
Add(attribute, (MemberResolverFactory)null);
|
|
||||||
Add(attribute, (MemberExpressionFactory)null);
|
|
||||||
}
|
|
||||||
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
|
|
||||||
#region Overrides
|
|
||||||
|
|
||||||
protected override Type MemberType(TMemberInfo info) => info.DeclaringType;
|
|
||||||
|
|
||||||
protected override IEnumerable<object> SelectMembers(Type type, IEnumerable<TMemberInfo> members, InjectionMember[] injectors)
|
|
||||||
{
|
|
||||||
// Select Injected Members
|
|
||||||
if (null != injectors)
|
|
||||||
{
|
|
||||||
foreach (var injectionMember in injectors)
|
|
||||||
{
|
|
||||||
if (injectionMember is InjectionMember<TMemberInfo, object[]>)
|
|
||||||
yield return injectionMember;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (null == members) yield break;
|
|
||||||
|
|
||||||
// Select Attributed members
|
|
||||||
foreach (var member in members)
|
|
||||||
{
|
|
||||||
if (ResolverFactories.Any(pair => member.IsDefined(pair.type)))
|
|
||||||
{
|
|
||||||
yield return member;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
|
|
||||||
#region Parameter Resolution Factories
|
|
||||||
|
|
||||||
protected virtual IEnumerable<ResolveDelegate<BuilderContext>> CreateParameterResolvers(ParameterInfo[] parameters, object[] injectors = null)
|
|
||||||
{
|
|
||||||
object[] resolvers = null != injectors && 0 == injectors.Length ? null : injectors;
|
|
||||||
for (var i = 0; i < parameters.Length; i++)
|
|
||||||
{
|
|
||||||
var parameter = parameters[i];
|
|
||||||
var resolver = null == resolvers ? parameter : PreProcessResolver(parameter, resolvers[i]);
|
|
||||||
|
|
||||||
// Check if has default value
|
|
||||||
var defaultValue = parameter.HasDefaultValue
|
|
||||||
? parameter.DefaultValue
|
|
||||||
: null;
|
|
||||||
|
|
||||||
// Check for registered attributes first
|
|
||||||
var expression = FromAttribute(parameter, defaultValue, resolver);
|
|
||||||
if (null == expression)
|
|
||||||
{
|
|
||||||
// Check if has default value
|
|
||||||
if (!parameter.HasDefaultValue)
|
|
||||||
{
|
|
||||||
// Plain vanilla case
|
|
||||||
expression = (ref BuilderContext context) => context.Resolve(parameter, null, resolver);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
expression = (ref BuilderContext context) =>
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
return context.Resolve(parameter, null, resolver);
|
|
||||||
}
|
|
||||||
catch
|
|
||||||
{
|
|
||||||
return defaultValue;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
yield return expression;
|
|
||||||
}
|
|
||||||
|
|
||||||
ResolveDelegate<BuilderContext> FromAttribute(ParameterInfo param, object defaultValue, object data)
|
|
||||||
{
|
|
||||||
foreach (var pair in ResolverFactories)
|
|
||||||
{
|
|
||||||
if (null == pair.factory) continue;
|
|
||||||
var attribute = param.GetCustomAttribute(pair.type);
|
|
||||||
if (null == attribute) continue;
|
|
||||||
|
|
||||||
// If found match, use provided factory to create expression
|
|
||||||
return pair.factory(attribute, param, data, defaultValue);
|
|
||||||
}
|
|
||||||
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
protected override ResolveDelegate<BuilderContext> DependencyResolverFactory(Attribute attribute, object info, object resolver, object defaultValue = null)
|
|
||||||
{
|
|
||||||
var parameter = (ParameterInfo)info;
|
|
||||||
|
|
||||||
if (!parameter.HasDefaultValue)
|
|
||||||
return (ref BuilderContext context) => context.Resolve((ParameterInfo)info, ((DependencyResolutionAttribute)attribute).Name, resolver);
|
|
||||||
else
|
|
||||||
{
|
|
||||||
return (ref BuilderContext context) =>
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
return context.Resolve((ParameterInfo)info, ((DependencyResolutionAttribute)attribute).Name, resolver);
|
|
||||||
}
|
|
||||||
catch
|
|
||||||
{
|
|
||||||
return defaultValue;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
protected override ResolveDelegate<BuilderContext> OptionalDependencyResolverFactory(Attribute attribute, object info, object resolver, object defaultValue = null)
|
|
||||||
{
|
|
||||||
var parameter = (ParameterInfo)info;
|
|
||||||
|
|
||||||
return (ref BuilderContext context) =>
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
return context.Resolve((ParameterInfo)info, ((DependencyResolutionAttribute)attribute).Name, resolver ?? OptionalDependencyAttribute.Instance);
|
|
||||||
}
|
|
||||||
catch
|
|
||||||
{
|
|
||||||
return defaultValue;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
|
|
||||||
#region Parameter Expression Factories
|
|
||||||
|
|
||||||
protected virtual IEnumerable<Expression> CreateParameterExpressions(ParameterInfo[] parameters, object[] injectors = null)
|
|
||||||
{
|
|
||||||
object[] resolvers = null != injectors && 0 == injectors.Length ? null : injectors;
|
|
||||||
for (var i = 0; i < parameters.Length; i++)
|
|
||||||
{
|
|
||||||
var parameter = parameters[i];
|
|
||||||
var resolver = null == resolvers ? parameter : PreProcessResolver(parameter, resolvers[i]);
|
|
||||||
|
|
||||||
// Check if has default value
|
|
||||||
var defaultValueExpr = parameter.HasDefaultValue
|
|
||||||
? Expression.Constant(parameter.DefaultValue, parameter.ParameterType)
|
|
||||||
: null;
|
|
||||||
|
|
||||||
// Check for registered attributes first
|
|
||||||
var expression = FromAttribute(parameter, defaultValueExpr, resolver);
|
|
||||||
if (null == expression)
|
|
||||||
{
|
|
||||||
// Check if has default value
|
|
||||||
if (!parameter.HasDefaultValue)
|
|
||||||
{
|
|
||||||
// Plain vanilla case
|
|
||||||
expression = ResolveExpression(parameter, null, resolver);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
var variable = Expression.Variable(parameter.ParameterType);
|
|
||||||
var resolve = ResolveExpression(parameter, null, resolver);
|
|
||||||
|
|
||||||
expression = Expression.Block(new[] { variable }, new Expression[]
|
|
||||||
{
|
|
||||||
Expression.TryCatch(
|
|
||||||
Expression.Assign(variable, resolve),
|
|
||||||
Expression.Catch(typeof(Exception),
|
|
||||||
Expression.Assign(variable, defaultValueExpr))),
|
|
||||||
variable
|
|
||||||
});
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
yield return expression;
|
|
||||||
}
|
|
||||||
|
|
||||||
Expression FromAttribute(ParameterInfo param, Expression member, object data)
|
|
||||||
{
|
|
||||||
foreach (var pair in ExpressionFactories)
|
|
||||||
{
|
|
||||||
if (null == pair.factory) continue;
|
|
||||||
var attribute = param.GetCustomAttribute(pair.type);
|
|
||||||
if (null == attribute) continue;
|
|
||||||
|
|
||||||
// If found match, use provided factory to create expression
|
|
||||||
return pair.factory(attribute, member, param, param.ParameterType, data);
|
|
||||||
}
|
|
||||||
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
protected override Expression DependencyExpressionFactory(Attribute attribute, Expression member, object info, Type type, object resolver)
|
|
||||||
{
|
|
||||||
var parameter = (ParameterInfo)info;
|
|
||||||
if (null == member)
|
|
||||||
{
|
|
||||||
// Plain vanilla case
|
|
||||||
return ResolveExpression(parameter, ((DependencyResolutionAttribute)attribute).Name, resolver);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// Has default value
|
|
||||||
var variable = Expression.Variable(parameter.ParameterType);
|
|
||||||
|
|
||||||
return Expression.Block(new[] { variable }, new Expression[]
|
|
||||||
{
|
|
||||||
Expression.TryCatch(
|
|
||||||
Expression.Assign(
|
|
||||||
variable,
|
|
||||||
ResolveExpression(parameter, ((DependencyResolutionAttribute)attribute).Name, resolver)),
|
|
||||||
Expression.Catch(typeof(Exception),
|
|
||||||
Expression.Assign(variable, member))),
|
|
||||||
variable
|
|
||||||
});
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
protected override Expression OptionalDependencyExpressionFactory(Attribute attribute, Expression member, object info, Type type, object resolver)
|
|
||||||
{
|
|
||||||
var parameter = (ParameterInfo)info;
|
|
||||||
var variable = Expression.Variable(parameter.ParameterType);
|
|
||||||
|
|
||||||
return Expression.Block(new[] { variable }, new Expression[]
|
|
||||||
{
|
|
||||||
Expression.TryCatch(
|
|
||||||
Expression.Assign(
|
|
||||||
variable,
|
|
||||||
ResolveExpression(parameter, ((DependencyResolutionAttribute)attribute).Name, resolver ?? OptionalDependencyAttribute.Instance)),
|
|
||||||
Expression.Catch(typeof(Exception),
|
|
||||||
Expression.Assign(variable, member ?? Expression.Constant(null, parameter.ParameterType)))),
|
|
||||||
variable
|
|
||||||
});
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
|
|
||||||
#region Expression Implementation
|
|
||||||
|
|
||||||
private Expression ResolveExpression(ParameterInfo parameter, string name, object resolver = null)
|
|
||||||
{
|
|
||||||
return Expression.Convert(
|
|
||||||
Expression.Call(BuilderContextExpression.Context, ResolveParameter,
|
|
||||||
Expression.Constant(parameter, typeof(ParameterInfo)),
|
|
||||||
Expression.Constant(name, typeof(string)),
|
|
||||||
Expression.Constant(resolver, typeof(object))),
|
|
||||||
parameter.ParameterType);
|
|
||||||
}
|
|
||||||
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
|
|
||||||
#region Implementation
|
|
||||||
|
|
||||||
private object PreProcessResolver(ParameterInfo parameter, object resolver)
|
|
||||||
{
|
|
||||||
switch (resolver)
|
|
||||||
{
|
|
||||||
case IResolve policy:
|
|
||||||
return (ResolveDelegate<BuilderContext>)policy.Resolve;
|
|
||||||
|
|
||||||
case IResolverFactory<ParameterInfo> factory:
|
|
||||||
return factory.GetResolver<BuilderContext>(parameter);
|
|
||||||
|
|
||||||
case Type type:
|
|
||||||
return typeof(Type) == parameter.ParameterType
|
|
||||||
? type : (object)parameter;
|
|
||||||
}
|
|
||||||
|
|
||||||
return resolver;
|
|
||||||
}
|
|
||||||
|
|
||||||
#endregion
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,59 +0,0 @@
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Reflection;
|
|
||||||
using Unity.Injection;
|
|
||||||
using Unity.Policy;
|
|
||||||
using Unity.Registration;
|
|
||||||
using Unity.Storage;
|
|
||||||
|
|
||||||
namespace Unity.Processors
|
|
||||||
{
|
|
||||||
public abstract partial class BuildMemberProcessor<TMemberInfo, TData> : ISelect<TMemberInfo>
|
|
||||||
{
|
|
||||||
#region ISelect
|
|
||||||
|
|
||||||
public IEnumerable<object> Select(Type type, IPolicySet registration)
|
|
||||||
{
|
|
||||||
return SelectMembers(type, DeclaredMembers(type),
|
|
||||||
((InternalRegistration) registration).InjectionMembers)
|
|
||||||
.Distinct();
|
|
||||||
}
|
|
||||||
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
|
|
||||||
#region Implementation
|
|
||||||
|
|
||||||
protected virtual IEnumerable<object> SelectMembers(Type type, IEnumerable<TMemberInfo> members, InjectionMember[] injectors)
|
|
||||||
{
|
|
||||||
// Select Injected Members
|
|
||||||
if (null != injectors)
|
|
||||||
{
|
|
||||||
foreach (var injectionMember in injectors)
|
|
||||||
{
|
|
||||||
if (injectionMember is InjectionMember<TMemberInfo, TData>)
|
|
||||||
yield return injectionMember;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (null == members) yield break;
|
|
||||||
|
|
||||||
// Select Attributed members
|
|
||||||
foreach (var member in members)
|
|
||||||
{
|
|
||||||
foreach (var pair in ExpressionFactories)
|
|
||||||
{
|
|
||||||
if (!member.IsDefined(pair.type)) continue;
|
|
||||||
|
|
||||||
yield return member;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
protected virtual IEnumerable<TMemberInfo> DeclaredMembers(Type type) => new TMemberInfo[0];
|
|
||||||
|
|
||||||
#endregion
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -75,7 +75,7 @@ namespace Unity.Processors
|
||||||
|
|
||||||
#region Expression Overrides
|
#region Expression Overrides
|
||||||
|
|
||||||
public override IEnumerable<Expression> GetBuildSteps(Type type, IPolicySet registration)
|
public override IEnumerable<Expression> GetExpressions(Type type, IPolicySet registration)
|
||||||
{
|
{
|
||||||
// Validate if Type could be created
|
// Validate if Type could be created
|
||||||
var exceptionExpr = ValidateConstructedTypeExpression(type);
|
var exceptionExpr = ValidateConstructedTypeExpression(type);
|
||||||
|
@ -132,7 +132,7 @@ namespace Unity.Processors
|
||||||
// Create 'new' expression
|
// Create 'new' expression
|
||||||
var ifThenExpr = Expression.IfThen(
|
var ifThenExpr = Expression.IfThen(
|
||||||
Expression.Equal(Expression.Constant(null), BuilderContextExpression.Existing),
|
Expression.Equal(Expression.Constant(null), BuilderContextExpression.Existing),
|
||||||
BuildMemberExpression(info, resolvers));
|
ExpressionFromMemberInfo(info, resolvers));
|
||||||
|
|
||||||
// Check if PerResolveLifetimeManager is required
|
// Check if PerResolveLifetimeManager is required
|
||||||
return lifetimeManager is PerResolveLifetimeManager
|
return lifetimeManager is PerResolveLifetimeManager
|
||||||
|
@ -140,7 +140,7 @@ namespace Unity.Processors
|
||||||
: new Expression[] { ifThenExpr };
|
: new Expression[] { ifThenExpr };
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override Expression BuildMemberExpression(ConstructorInfo info, object[] resolvers)
|
protected override Expression ExpressionFromMemberInfo(ConstructorInfo info, object[] resolvers)
|
||||||
{
|
{
|
||||||
// Check if had ByRef parameters
|
// Check if had ByRef parameters
|
||||||
var parameters = info.GetParameters();
|
var parameters = info.GetParameters();
|
||||||
|
|
|
@ -53,7 +53,7 @@ namespace Unity.Processors
|
||||||
|
|
||||||
#region Overrides
|
#region Overrides
|
||||||
|
|
||||||
public override IEnumerable<Expression> GetBuildSteps(Type type, IPolicySet registration)
|
public override IEnumerable<Expression> GetExpressions(Type type, IPolicySet registration)
|
||||||
{
|
{
|
||||||
// Select ConstructorInfo
|
// Select ConstructorInfo
|
||||||
var selector = GetPolicy<ISelect<ConstructorInfo>>(registration);
|
var selector = GetPolicy<ISelect<ConstructorInfo>>(registration);
|
||||||
|
|
|
@ -5,10 +5,11 @@ using System.Linq;
|
||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
using Unity.Injection;
|
using Unity.Injection;
|
||||||
using Unity.Policy;
|
using Unity.Policy;
|
||||||
|
using Unity.Registration;
|
||||||
|
|
||||||
namespace Unity.Processors
|
namespace Unity.Processors
|
||||||
{
|
{
|
||||||
public partial class ConstructorProcessor : MethodBaseInfoProcessor<ConstructorInfo>
|
public partial class ConstructorProcessor : MethodBaseProcessor<ConstructorInfo>
|
||||||
{
|
{
|
||||||
#region Fields
|
#region Fields
|
||||||
|
|
||||||
|
@ -39,6 +40,41 @@ namespace Unity.Processors
|
||||||
|
|
||||||
#region Overrides
|
#region Overrides
|
||||||
|
|
||||||
|
public override IEnumerable<object> Select(Type type, IPolicySet registration)
|
||||||
|
{
|
||||||
|
// Select Injected Members
|
||||||
|
if (null != ((InternalRegistration)registration).InjectionMembers)
|
||||||
|
{
|
||||||
|
foreach (var injectionMember in ((InternalRegistration)registration).InjectionMembers)
|
||||||
|
{
|
||||||
|
if (injectionMember is InjectionMember<ConstructorInfo, object[]>)
|
||||||
|
{
|
||||||
|
return new[] { injectionMember };
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Enumerate to array
|
||||||
|
var constructors = DeclaredMembers(type).ToArray();
|
||||||
|
if (1 >= constructors.Length)
|
||||||
|
return constructors;
|
||||||
|
|
||||||
|
// Select Attributed constructors
|
||||||
|
foreach (var constructor in constructors)
|
||||||
|
{
|
||||||
|
for (var i = 0; i < AttributeFactories.Length; i++)
|
||||||
|
{
|
||||||
|
if (!constructor.IsDefined(AttributeFactories[i].Type))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
return new[] { constructor };
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Select default
|
||||||
|
return new[] { SelectMethod(type, constructors) };
|
||||||
|
}
|
||||||
|
|
||||||
protected override IEnumerable<ConstructorInfo> DeclaredMembers(Type type)
|
protected override IEnumerable<ConstructorInfo> DeclaredMembers(Type type)
|
||||||
{
|
{
|
||||||
#if NETSTANDARD1_0
|
#if NETSTANDARD1_0
|
||||||
|
@ -50,51 +86,6 @@ namespace Unity.Processors
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override IEnumerable<object> SelectMembers(Type type, IEnumerable<ConstructorInfo> members, InjectionMember[] injectors)
|
|
||||||
{
|
|
||||||
// Select Injected Members
|
|
||||||
if (null != injectors)
|
|
||||||
{
|
|
||||||
foreach (var injectionMember in injectors)
|
|
||||||
{
|
|
||||||
if (injectionMember is InjectionMember<ConstructorInfo, object[]>)
|
|
||||||
{
|
|
||||||
yield return injectionMember;
|
|
||||||
yield break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (null == members) yield break;
|
|
||||||
|
|
||||||
// Enumerate to array
|
|
||||||
var constructors = members.ToArray();
|
|
||||||
switch (constructors.Length)
|
|
||||||
{
|
|
||||||
case 0:
|
|
||||||
yield break;
|
|
||||||
|
|
||||||
case 1:
|
|
||||||
yield return constructors[0];
|
|
||||||
yield break;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Select Attributed members
|
|
||||||
foreach (var constructor in constructors)
|
|
||||||
{
|
|
||||||
foreach (var pair in ResolverFactories)
|
|
||||||
{
|
|
||||||
if (!constructor.IsDefined(pair.type)) continue;
|
|
||||||
|
|
||||||
yield return constructor;
|
|
||||||
yield break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Select default
|
|
||||||
yield return SelectMethod(type, constructors);
|
|
||||||
}
|
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,28 @@
|
||||||
|
using System.Linq.Expressions;
|
||||||
|
using System.Reflection;
|
||||||
|
using Unity.Builder;
|
||||||
|
|
||||||
|
namespace Unity.Processors
|
||||||
|
{
|
||||||
|
public partial class FieldsProcessor
|
||||||
|
{
|
||||||
|
|
||||||
|
|
||||||
|
#region Overrides
|
||||||
|
|
||||||
|
protected override Expression GetResolverExpression(FieldInfo field, string name, object resolver)
|
||||||
|
{
|
||||||
|
return Expression.Convert(
|
||||||
|
Expression.Call(BuilderContextExpression.Context, ResolveField,
|
||||||
|
Expression.Constant(field, typeof(FieldInfo)),
|
||||||
|
Expression.Constant(name, typeof(string)),
|
||||||
|
Expression.Constant(PreProcessResolver(field, resolver), typeof(object))),
|
||||||
|
field.FieldType);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override MemberExpression CreateMemberExpression(FieldInfo info)
|
||||||
|
=> Expression.Field(Expression.Convert(BuilderContextExpression.Existing, info.DeclaringType), info);
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,59 @@
|
||||||
|
using System;
|
||||||
|
using System.Reflection;
|
||||||
|
using Unity.Builder;
|
||||||
|
using Unity.Policy;
|
||||||
|
|
||||||
|
namespace Unity.Processors
|
||||||
|
{
|
||||||
|
public partial class FieldsProcessor
|
||||||
|
{
|
||||||
|
#region Overrides
|
||||||
|
|
||||||
|
protected override ResolveDelegate<BuilderContext> GetResolverDelegate(FieldInfo info, object resolver)
|
||||||
|
{
|
||||||
|
var value = PreProcessResolver(info, resolver);
|
||||||
|
return (ref BuilderContext context) =>
|
||||||
|
{
|
||||||
|
info.SetValue(context.Existing, context.Resolve(info, context.Name, value));
|
||||||
|
return context.Existing;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#region Parameter Resolver Factories
|
||||||
|
|
||||||
|
protected override ResolveDelegate<BuilderContext> DependencyResolverFactory(Attribute attribute, object info, object resolver, object defaultValue = null)
|
||||||
|
{
|
||||||
|
return (ref BuilderContext context) =>
|
||||||
|
{
|
||||||
|
((FieldInfo)info).SetValue(context.Existing,
|
||||||
|
context.Resolve((FieldInfo)info, ((DependencyResolutionAttribute)attribute).Name, resolver ?? DependencyAttribute.Instance));
|
||||||
|
|
||||||
|
return context.Existing;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override ResolveDelegate<BuilderContext> OptionalDependencyResolverFactory(Attribute attribute, object info, object resolver, object defaultValue = null)
|
||||||
|
{
|
||||||
|
return (ref BuilderContext context) =>
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
((FieldInfo)info).SetValue(context.Existing,
|
||||||
|
context.Resolve((FieldInfo)info, ((DependencyResolutionAttribute)attribute).Name, resolver ?? OptionalDependencyAttribute.Instance));
|
||||||
|
return context.Existing;
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
((FieldInfo)info).SetValue(context.Existing, defaultValue);
|
||||||
|
return context.Existing;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,15 +1,13 @@
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Linq.Expressions;
|
|
||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
using Unity.Builder;
|
using Unity.Builder;
|
||||||
using Unity.Policy;
|
using Unity.Policy;
|
||||||
using Unity.Storage;
|
|
||||||
|
|
||||||
namespace Unity.Processors
|
namespace Unity.Processors
|
||||||
{
|
{
|
||||||
public class FieldsProcessor : BuildMemberProcessor<FieldInfo, object>
|
public partial class FieldsProcessor : MemberProcessor<FieldInfo, object>
|
||||||
{
|
{
|
||||||
#region Fields
|
#region Fields
|
||||||
|
|
||||||
|
@ -50,67 +48,11 @@ namespace Unity.Processors
|
||||||
|
|
||||||
protected override Type MemberType(FieldInfo info) => info.FieldType;
|
protected override Type MemberType(FieldInfo info) => info.FieldType;
|
||||||
|
|
||||||
protected override ResolveDelegate<BuilderContext> GetResolver(FieldInfo info, object resolver)
|
|
||||||
{
|
|
||||||
var value = PreProcessResolver(info, resolver);
|
|
||||||
return (ref BuilderContext context) =>
|
|
||||||
{
|
|
||||||
info.SetValue(context.Existing, context.Resolve(info, context.Name, value));
|
|
||||||
return context.Existing;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
protected override Expression GetExpression(FieldInfo field, string name, object resolver)
|
|
||||||
{
|
|
||||||
return Expression.Convert(
|
|
||||||
Expression.Call(BuilderContextExpression.Context, ResolveField,
|
|
||||||
Expression.Constant(field, typeof(FieldInfo)),
|
|
||||||
Expression.Constant(name, typeof(string)),
|
|
||||||
Expression.Constant(PreProcessResolver(field, resolver), typeof(object))),
|
|
||||||
field.FieldType);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected override MemberExpression CreateMemberExpression(FieldInfo info)
|
|
||||||
=> Expression.Field(Expression.Convert(BuilderContextExpression.Existing, info.DeclaringType), info);
|
|
||||||
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
|
|
||||||
#region Parameter Resolver Factories
|
|
||||||
|
|
||||||
protected override ResolveDelegate<BuilderContext> DependencyResolverFactory(Attribute attribute, object info, object resolver, object defaultValue = null)
|
|
||||||
{
|
|
||||||
return (ref BuilderContext context) =>
|
|
||||||
{
|
|
||||||
((FieldInfo)info).SetValue(context.Existing,
|
|
||||||
context.Resolve((FieldInfo)info, ((DependencyResolutionAttribute)attribute).Name, resolver ?? DependencyAttribute.Instance));
|
|
||||||
|
|
||||||
return context.Existing;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
protected override ResolveDelegate<BuilderContext> OptionalDependencyResolverFactory(Attribute attribute, object info, object resolver, object defaultValue = null)
|
|
||||||
{
|
|
||||||
return (ref BuilderContext context) =>
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
((FieldInfo)info).SetValue(context.Existing,
|
|
||||||
context.Resolve((FieldInfo)info, ((DependencyResolutionAttribute)attribute).Name, resolver ?? OptionalDependencyAttribute.Instance));
|
|
||||||
return context.Existing;
|
|
||||||
}
|
|
||||||
catch
|
|
||||||
{
|
|
||||||
((FieldInfo)info).SetValue(context.Existing, defaultValue);
|
|
||||||
return context.Existing;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
|
|
||||||
#region Implementation
|
#region Implementation
|
||||||
|
#if NETSTANDARD1_0
|
||||||
|
|
||||||
public static IEnumerable<FieldInfo> GetFieldsHierarchical(Type type)
|
public static IEnumerable<FieldInfo> GetFieldsHierarchical(Type type)
|
||||||
{
|
{
|
||||||
|
@ -128,25 +70,7 @@ namespace Unity.Processors
|
||||||
.DeclaredFields
|
.DeclaredFields
|
||||||
.Concat(GetFieldsHierarchical(type.GetTypeInfo().BaseType));
|
.Concat(GetFieldsHierarchical(type.GetTypeInfo().BaseType));
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
private object PreProcessResolver(FieldInfo field, object resolver)
|
|
||||||
{
|
|
||||||
switch (resolver)
|
|
||||||
{
|
|
||||||
case IResolve policy:
|
|
||||||
return (ResolveDelegate<BuilderContext>)policy.Resolve;
|
|
||||||
|
|
||||||
case IResolverFactory factory:
|
|
||||||
return factory.GetResolver<BuilderContext>(field.FieldType);
|
|
||||||
|
|
||||||
case Type type:
|
|
||||||
return typeof(Type) == field.FieldType
|
|
||||||
? type : (object)field;
|
|
||||||
}
|
|
||||||
|
|
||||||
return resolver;
|
|
||||||
}
|
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,139 @@
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq.Expressions;
|
||||||
|
using System.Reflection;
|
||||||
|
using Unity.Builder;
|
||||||
|
|
||||||
|
namespace Unity.Processors
|
||||||
|
{
|
||||||
|
public abstract partial class MethodBaseProcessor<TMemberInfo>
|
||||||
|
{
|
||||||
|
#region Parameter Factory
|
||||||
|
|
||||||
|
protected virtual IEnumerable<Expression> CreateParameterExpressions(ParameterInfo[] parameters, object[] injectors = null)
|
||||||
|
{
|
||||||
|
object[] resolvers = null != injectors && 0 == injectors.Length ? null : injectors;
|
||||||
|
for (var i = 0; i < parameters.Length; i++)
|
||||||
|
{
|
||||||
|
var parameter = parameters[i];
|
||||||
|
var resolver = null == resolvers ? parameter : PreProcessResolver(parameter, resolvers[i]);
|
||||||
|
|
||||||
|
// Check if has default value
|
||||||
|
var defaultValueExpr = parameter.HasDefaultValue
|
||||||
|
? Expression.Constant(parameter.DefaultValue, parameter.ParameterType)
|
||||||
|
: null;
|
||||||
|
|
||||||
|
// Check for registered attributes first
|
||||||
|
var expression = FromAttribute(parameter, defaultValueExpr, resolver);
|
||||||
|
if (null == expression)
|
||||||
|
{
|
||||||
|
// Check if has default value
|
||||||
|
if (!parameter.HasDefaultValue)
|
||||||
|
{
|
||||||
|
// Plain vanilla case
|
||||||
|
expression = CallResolveExpression(parameter, null, resolver);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
var variable = Expression.Variable(parameter.ParameterType);
|
||||||
|
var resolve = CallResolveExpression(parameter, null, resolver);
|
||||||
|
|
||||||
|
expression = Expression.Block(new[] { variable }, new Expression[]
|
||||||
|
{
|
||||||
|
Expression.TryCatch(
|
||||||
|
Expression.Assign(variable, resolve),
|
||||||
|
Expression.Catch(typeof(Exception),
|
||||||
|
Expression.Assign(variable, defaultValueExpr))),
|
||||||
|
variable
|
||||||
|
});
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
yield return expression;
|
||||||
|
}
|
||||||
|
|
||||||
|
Expression FromAttribute(ParameterInfo param, Expression member, object data)
|
||||||
|
{
|
||||||
|
foreach (var node in AttributeFactories)
|
||||||
|
{
|
||||||
|
if (null == node.ExpressionFactory) continue;
|
||||||
|
var attribute = param.GetCustomAttribute(node.Type);
|
||||||
|
if (null == attribute) continue;
|
||||||
|
|
||||||
|
// If found match, use provided factory to create expression
|
||||||
|
return node.ExpressionFactory(attribute, member, param, param.ParameterType, data);
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
|
||||||
|
#region Attribute Factory
|
||||||
|
|
||||||
|
protected override Expression DependencyExpressionFactory(Attribute attribute, Expression member, object info, Type type, object resolver)
|
||||||
|
{
|
||||||
|
var parameter = (ParameterInfo)info;
|
||||||
|
if (null == member)
|
||||||
|
{
|
||||||
|
// Plain vanilla case
|
||||||
|
return CallResolveExpression(parameter, ((DependencyResolutionAttribute)attribute).Name, resolver);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Has default value
|
||||||
|
var variable = Expression.Variable(parameter.ParameterType);
|
||||||
|
|
||||||
|
return Expression.Block(new[] { variable }, new Expression[]
|
||||||
|
{
|
||||||
|
Expression.TryCatch(
|
||||||
|
Expression.Assign(
|
||||||
|
variable,
|
||||||
|
CallResolveExpression(parameter, ((DependencyResolutionAttribute)attribute).Name, resolver)),
|
||||||
|
Expression.Catch(typeof(Exception),
|
||||||
|
Expression.Assign(variable, member))),
|
||||||
|
variable
|
||||||
|
});
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override Expression OptionalDependencyExpressionFactory(Attribute attribute, Expression member, object info, Type type, object resolver)
|
||||||
|
{
|
||||||
|
var parameter = (ParameterInfo)info;
|
||||||
|
var variable = Expression.Variable(parameter.ParameterType);
|
||||||
|
|
||||||
|
return Expression.Block(new[] { variable }, new Expression[]
|
||||||
|
{
|
||||||
|
Expression.TryCatch(
|
||||||
|
Expression.Assign(
|
||||||
|
variable,
|
||||||
|
CallResolveExpression(parameter, ((DependencyResolutionAttribute)attribute).Name, resolver ?? OptionalDependencyAttribute.Instance)),
|
||||||
|
Expression.Catch(typeof(Exception),
|
||||||
|
Expression.Assign(variable, member ?? Expression.Constant(null, parameter.ParameterType)))),
|
||||||
|
variable
|
||||||
|
});
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
|
||||||
|
#region Implementation
|
||||||
|
|
||||||
|
private Expression CallResolveExpression(ParameterInfo parameter, string name, object resolver = null)
|
||||||
|
{
|
||||||
|
return Expression.Convert(
|
||||||
|
Expression.Call(BuilderContextExpression.Context, ResolveParameter,
|
||||||
|
Expression.Constant(parameter, typeof(ParameterInfo)),
|
||||||
|
Expression.Constant(name, typeof(string)),
|
||||||
|
Expression.Constant(resolver, typeof(object))),
|
||||||
|
parameter.ParameterType);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,67 @@
|
||||||
|
using System;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Reflection;
|
||||||
|
using Unity.Builder;
|
||||||
|
using Unity.Policy;
|
||||||
|
|
||||||
|
namespace Unity.Processors
|
||||||
|
{
|
||||||
|
public abstract partial class MethodBaseProcessor<TMemberInfo> : MemberProcessor<TMemberInfo, object[]>
|
||||||
|
where TMemberInfo : MethodBase
|
||||||
|
{
|
||||||
|
#region Fields
|
||||||
|
|
||||||
|
private readonly MethodInfo ResolveParameter =
|
||||||
|
typeof(BuilderContext).GetTypeInfo()
|
||||||
|
.GetDeclaredMethods(nameof(BuilderContext.Resolve))
|
||||||
|
.First(m =>
|
||||||
|
{
|
||||||
|
var parameters = m.GetParameters();
|
||||||
|
return 2 <= parameters.Length &&
|
||||||
|
typeof(ParameterInfo) == parameters[0].ParameterType;
|
||||||
|
});
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
|
||||||
|
#region Constructors
|
||||||
|
|
||||||
|
protected MethodBaseProcessor(IPolicySet policySet, Type attribute)
|
||||||
|
: base(policySet)
|
||||||
|
{
|
||||||
|
Add(attribute, (ExpressionAttributeFactory)null, (ResolutionAttributeFactory)null);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
|
||||||
|
#region Overrides
|
||||||
|
|
||||||
|
protected override Type MemberType(TMemberInfo info) => info.DeclaringType;
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
|
||||||
|
#region Implementation
|
||||||
|
|
||||||
|
private object PreProcessResolver(ParameterInfo parameter, object resolver)
|
||||||
|
{
|
||||||
|
switch (resolver)
|
||||||
|
{
|
||||||
|
case IResolve policy:
|
||||||
|
return (ResolveDelegate<BuilderContext>)policy.Resolve;
|
||||||
|
|
||||||
|
case IResolverFactory<ParameterInfo> factory:
|
||||||
|
return factory.GetResolver<BuilderContext>(parameter);
|
||||||
|
|
||||||
|
case Type type:
|
||||||
|
return typeof(Type) == parameter.ParameterType
|
||||||
|
? type : (object)parameter;
|
||||||
|
}
|
||||||
|
|
||||||
|
return resolver;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,116 @@
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Reflection;
|
||||||
|
using Unity.Builder;
|
||||||
|
using Unity.Policy;
|
||||||
|
|
||||||
|
namespace Unity.Processors
|
||||||
|
{
|
||||||
|
public abstract partial class MethodBaseProcessor<TMemberInfo>
|
||||||
|
{
|
||||||
|
#region Parameter Factory
|
||||||
|
|
||||||
|
protected virtual IEnumerable<ResolveDelegate<BuilderContext>> CreateParameterResolvers(ParameterInfo[] parameters, object[] injectors = null)
|
||||||
|
{
|
||||||
|
object[] resolvers = null != injectors && 0 == injectors.Length ? null : injectors;
|
||||||
|
for (var i = 0; i < parameters.Length; i++)
|
||||||
|
{
|
||||||
|
var parameter = parameters[i];
|
||||||
|
var resolver = null == resolvers ? parameter : PreProcessResolver(parameter, resolvers[i]);
|
||||||
|
|
||||||
|
// Check if has default value
|
||||||
|
var defaultValue = parameter.HasDefaultValue
|
||||||
|
? parameter.DefaultValue
|
||||||
|
: null;
|
||||||
|
|
||||||
|
// Check for registered attributes first
|
||||||
|
var expression = FromAttribute(parameter, defaultValue, resolver);
|
||||||
|
if (null == expression)
|
||||||
|
{
|
||||||
|
// Check if has default value
|
||||||
|
if (!parameter.HasDefaultValue)
|
||||||
|
{
|
||||||
|
// Plain vanilla case
|
||||||
|
expression = (ref BuilderContext context) => context.Resolve(parameter, null, resolver);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
expression = (ref BuilderContext context) =>
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
return context.Resolve(parameter, null, resolver);
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
return defaultValue;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
yield return expression;
|
||||||
|
}
|
||||||
|
|
||||||
|
ResolveDelegate<BuilderContext> FromAttribute(ParameterInfo param, object defaultValue, object data)
|
||||||
|
{
|
||||||
|
foreach (var node in AttributeFactories)
|
||||||
|
{
|
||||||
|
if (null == node.ResolutionFactory) continue;
|
||||||
|
var attribute = param.GetCustomAttribute(node.Type);
|
||||||
|
if (null == attribute) continue;
|
||||||
|
|
||||||
|
// If found match, use provided factory to create expression
|
||||||
|
return node.ResolutionFactory(attribute, param, data, defaultValue);
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Attribute Factory
|
||||||
|
|
||||||
|
protected override ResolveDelegate<BuilderContext> DependencyResolverFactory(Attribute attribute, object info, object resolver, object defaultValue = null)
|
||||||
|
{
|
||||||
|
var parameter = (ParameterInfo)info;
|
||||||
|
|
||||||
|
if (!parameter.HasDefaultValue)
|
||||||
|
return (ref BuilderContext context) => context.Resolve((ParameterInfo)info, ((DependencyResolutionAttribute)attribute).Name, resolver);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return (ref BuilderContext context) =>
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
return context.Resolve((ParameterInfo)info, ((DependencyResolutionAttribute)attribute).Name, resolver);
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
return defaultValue;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override ResolveDelegate<BuilderContext> OptionalDependencyResolverFactory(Attribute attribute, object info, object resolver, object defaultValue = null)
|
||||||
|
{
|
||||||
|
var parameter = (ParameterInfo)info;
|
||||||
|
|
||||||
|
return (ref BuilderContext context) =>
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
return context.Resolve((ParameterInfo)info, ((DependencyResolutionAttribute)attribute).Name, resolver ?? OptionalDependencyAttribute.Instance);
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
return defaultValue;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,29 @@
|
||||||
|
using System.Linq.Expressions;
|
||||||
|
using System.Reflection;
|
||||||
|
using Unity.Builder;
|
||||||
|
|
||||||
|
namespace Unity.Processors
|
||||||
|
{
|
||||||
|
public partial class MethodProcessor
|
||||||
|
{
|
||||||
|
#region Building Expression
|
||||||
|
|
||||||
|
protected override Expression ExpressionFromMemberInfo(MethodInfo info)
|
||||||
|
{
|
||||||
|
ValidateMethod(info);
|
||||||
|
|
||||||
|
return Expression.Call(Expression.Convert(BuilderContextExpression.Existing, info.DeclaringType),
|
||||||
|
info, CreateParameterExpressions(info.GetParameters()));
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override Expression ExpressionFromMemberInfo(MethodInfo info, object[] resolvers)
|
||||||
|
{
|
||||||
|
ValidateMethod(info);
|
||||||
|
|
||||||
|
return Expression.Call(Expression.Convert(BuilderContextExpression.Existing, info.DeclaringType),
|
||||||
|
info, CreateParameterExpressions(info.GetParameters(), resolvers));
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,58 @@
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Globalization;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Reflection;
|
||||||
|
using Unity.Exceptions;
|
||||||
|
using Unity.Policy;
|
||||||
|
using Unity.Utility;
|
||||||
|
|
||||||
|
namespace Unity.Processors
|
||||||
|
{
|
||||||
|
public partial class MethodProcessor : MethodBaseProcessor<MethodInfo>
|
||||||
|
{
|
||||||
|
#region Constructors
|
||||||
|
|
||||||
|
public MethodProcessor(IPolicySet policySet)
|
||||||
|
: base(policySet, typeof(InjectionMethodAttribute))
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
|
||||||
|
#region Selection
|
||||||
|
|
||||||
|
protected override IEnumerable<MethodInfo> DeclaredMembers(Type type)
|
||||||
|
{
|
||||||
|
#if NETSTANDARD1_0
|
||||||
|
return type.GetMethodsHierarchical()
|
||||||
|
.Where(c => c.IsStatic == false && c.IsPublic);
|
||||||
|
#else
|
||||||
|
return type.GetMethods(BindingFlags.Instance | BindingFlags.Public);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
|
||||||
|
#region Implementation
|
||||||
|
|
||||||
|
private void ValidateMethod(MethodInfo info)
|
||||||
|
{
|
||||||
|
var parameters = info.GetParameters();
|
||||||
|
if (info.IsGenericMethodDefinition || parameters.Any(param => param.IsOut || param.ParameterType.IsByRef))
|
||||||
|
{
|
||||||
|
var format = info.IsGenericMethodDefinition
|
||||||
|
? "The method {1} on type {0} is marked for injection, but it is an open generic method. Injection cannot be performed."
|
||||||
|
: "The method {1} on type {0} has an out parameter. Injection cannot be performed.";
|
||||||
|
|
||||||
|
throw new IllegalInjectionMethodException(string.Format(CultureInfo.CurrentCulture,
|
||||||
|
format, info.DeclaringType.GetTypeInfo().Name, info.Name));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,52 @@
|
||||||
|
using System.Linq;
|
||||||
|
using System.Reflection;
|
||||||
|
using Unity.Builder;
|
||||||
|
using Unity.Policy;
|
||||||
|
|
||||||
|
namespace Unity.Processors
|
||||||
|
{
|
||||||
|
public partial class MethodProcessor
|
||||||
|
{
|
||||||
|
#region Building Resolver
|
||||||
|
|
||||||
|
protected override ResolveDelegate<BuilderContext> ResolverFromMemberInfo(MethodInfo info)
|
||||||
|
{
|
||||||
|
ValidateMethod(info);
|
||||||
|
|
||||||
|
var parameterResolvers = CreateParameterResolvers(info.GetParameters()).ToArray();
|
||||||
|
return (ref BuilderContext c) =>
|
||||||
|
{
|
||||||
|
if (null == c.Existing) return c.Existing;
|
||||||
|
|
||||||
|
var parameters = new object[parameterResolvers.Length];
|
||||||
|
for (var i = 0; i < parameters.Length; i++)
|
||||||
|
parameters[i] = parameterResolvers[i](ref c);
|
||||||
|
|
||||||
|
info.Invoke(c.Existing, parameters);
|
||||||
|
|
||||||
|
return c.Existing;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override ResolveDelegate<BuilderContext> ResolverFromMemberInfo(MethodInfo info, object[] resolvers)
|
||||||
|
{
|
||||||
|
ValidateMethod(info);
|
||||||
|
|
||||||
|
var parameterResolvers = CreateParameterResolvers(info.GetParameters(), resolvers).ToArray();
|
||||||
|
return (ref BuilderContext c) =>
|
||||||
|
{
|
||||||
|
if (null == c.Existing) return c.Existing;
|
||||||
|
|
||||||
|
var parameters = new object[parameterResolvers.Length];
|
||||||
|
for (var i = 0; i < parameters.Length; i++)
|
||||||
|
parameters[i] = parameterResolvers[i](ref c);
|
||||||
|
|
||||||
|
info.Invoke(c.Existing, parameters);
|
||||||
|
|
||||||
|
return c.Existing;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,125 +0,0 @@
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Globalization;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Linq.Expressions;
|
|
||||||
using System.Reflection;
|
|
||||||
using Unity.Builder;
|
|
||||||
using Unity.Exceptions;
|
|
||||||
using Unity.Policy;
|
|
||||||
using Unity.Storage;
|
|
||||||
using Unity.Utility;
|
|
||||||
|
|
||||||
namespace Unity.Processors
|
|
||||||
{
|
|
||||||
public class MethodsProcessor : MethodBaseInfoProcessor<MethodInfo>
|
|
||||||
{
|
|
||||||
#region Constructors
|
|
||||||
|
|
||||||
public MethodsProcessor(IPolicySet policySet)
|
|
||||||
: base(policySet, typeof(InjectionMethodAttribute))
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
|
|
||||||
#region Selection
|
|
||||||
|
|
||||||
protected override IEnumerable<MethodInfo> DeclaredMembers(Type type)
|
|
||||||
{
|
|
||||||
#if NETSTANDARD1_0
|
|
||||||
return type.GetMethodsHierarchical()
|
|
||||||
.Where(c => c.IsStatic == false && c.IsPublic);
|
|
||||||
#else
|
|
||||||
return type.GetMethods(BindingFlags.Instance | BindingFlags.Public);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
|
|
||||||
#region Building Expression
|
|
||||||
|
|
||||||
protected override Expression BuildMemberExpression(MethodInfo info)
|
|
||||||
{
|
|
||||||
ValidateMethod(info);
|
|
||||||
|
|
||||||
return Expression.Call(Expression.Convert(BuilderContextExpression.Existing, info.DeclaringType),
|
|
||||||
info, CreateParameterExpressions(info.GetParameters()));
|
|
||||||
}
|
|
||||||
|
|
||||||
protected override Expression BuildMemberExpression(MethodInfo info, object[] resolvers)
|
|
||||||
{
|
|
||||||
ValidateMethod(info);
|
|
||||||
|
|
||||||
return Expression.Call(Expression.Convert(BuilderContextExpression.Existing, info.DeclaringType),
|
|
||||||
info, CreateParameterExpressions(info.GetParameters(), resolvers));
|
|
||||||
}
|
|
||||||
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
|
|
||||||
#region Building Resolver
|
|
||||||
|
|
||||||
protected override ResolveDelegate<BuilderContext> BuildMemberResolver(MethodInfo info)
|
|
||||||
{
|
|
||||||
ValidateMethod(info);
|
|
||||||
|
|
||||||
var parameterResolvers = CreateParameterResolvers(info.GetParameters()).ToArray();
|
|
||||||
return (ref BuilderContext c) =>
|
|
||||||
{
|
|
||||||
if (null == c.Existing) return c.Existing;
|
|
||||||
|
|
||||||
var parameters = new object[parameterResolvers.Length];
|
|
||||||
for (var i = 0; i < parameters.Length; i++)
|
|
||||||
parameters[i] = parameterResolvers[i](ref c);
|
|
||||||
|
|
||||||
info.Invoke(c.Existing, parameters);
|
|
||||||
|
|
||||||
return c.Existing;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
protected override ResolveDelegate<BuilderContext> BuildMemberResolver(MethodInfo info, object[] resolvers)
|
|
||||||
{
|
|
||||||
ValidateMethod(info);
|
|
||||||
|
|
||||||
var parameterResolvers = CreateParameterResolvers(info.GetParameters(), resolvers).ToArray();
|
|
||||||
return (ref BuilderContext c) =>
|
|
||||||
{
|
|
||||||
if (null == c.Existing) return c.Existing;
|
|
||||||
|
|
||||||
var parameters = new object[parameterResolvers.Length];
|
|
||||||
for (var i = 0; i < parameters.Length; i++)
|
|
||||||
parameters[i] = parameterResolvers[i](ref c);
|
|
||||||
|
|
||||||
info.Invoke(c.Existing, parameters);
|
|
||||||
|
|
||||||
return c.Existing;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
|
|
||||||
#region Implementation
|
|
||||||
|
|
||||||
private void ValidateMethod(MethodInfo info)
|
|
||||||
{
|
|
||||||
var parameters = info.GetParameters();
|
|
||||||
if (info.IsGenericMethodDefinition || parameters.Any(param => param.IsOut || param.ParameterType.IsByRef))
|
|
||||||
{
|
|
||||||
var format = info.IsGenericMethodDefinition
|
|
||||||
? "The method {1} on type {0} is marked for injection, but it is an open generic method. Injection cannot be performed."
|
|
||||||
: "The method {1} on type {0} has an out parameter. Injection cannot be performed.";
|
|
||||||
|
|
||||||
throw new IllegalInjectionMethodException(string.Format(CultureInfo.CurrentCulture,
|
|
||||||
format, info.DeclaringType.GetTypeInfo().Name, info.Name));
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
#endregion
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,167 +0,0 @@
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Linq.Expressions;
|
|
||||||
using System.Reflection;
|
|
||||||
using Unity.Builder;
|
|
||||||
using Unity.Policy;
|
|
||||||
using Unity.Storage;
|
|
||||||
using Unity.Utility;
|
|
||||||
|
|
||||||
namespace Unity.Processors
|
|
||||||
{
|
|
||||||
public class PropertiesProcessor : BuildMemberProcessor<PropertyInfo, object>
|
|
||||||
{
|
|
||||||
#region Fields
|
|
||||||
|
|
||||||
public static readonly MethodInfo ResolveProperty =
|
|
||||||
typeof(BuilderContext).GetTypeInfo()
|
|
||||||
.GetDeclaredMethods(nameof(BuilderContext.Resolve))
|
|
||||||
.First(m =>
|
|
||||||
{
|
|
||||||
var parameters = m.GetParameters();
|
|
||||||
return 2 <= parameters.Length &&
|
|
||||||
typeof(PropertyInfo) == parameters[0].ParameterType;
|
|
||||||
});
|
|
||||||
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
|
|
||||||
#region Constructors
|
|
||||||
|
|
||||||
public PropertiesProcessor(IPolicySet policySet)
|
|
||||||
: base(policySet)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
|
|
||||||
#region Overrides
|
|
||||||
|
|
||||||
protected override IEnumerable<PropertyInfo> DeclaredMembers(Type type)
|
|
||||||
{
|
|
||||||
#if NETSTANDARD1_0
|
|
||||||
return GetPropertiesHierarchical(type)
|
|
||||||
.Where(p =>
|
|
||||||
{
|
|
||||||
if (!p.CanWrite) return false;
|
|
||||||
|
|
||||||
var propertyMethod = p.GetSetMethod(true) ??
|
|
||||||
p.GetGetMethod(true);
|
|
||||||
|
|
||||||
// Skip static properties and indexers.
|
|
||||||
if (propertyMethod.IsStatic || p.GetIndexParameters().Length != 0)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
return true;
|
|
||||||
});
|
|
||||||
#else
|
|
||||||
return type.GetProperties(BindingFlags.Instance | BindingFlags.Public)
|
|
||||||
.Where(p => p.CanWrite && p.GetIndexParameters().Length == 0);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
protected override Type MemberType(PropertyInfo info)
|
|
||||||
=> info.PropertyType;
|
|
||||||
|
|
||||||
protected override ResolveDelegate<BuilderContext> GetResolver(PropertyInfo info, object resolver)
|
|
||||||
{
|
|
||||||
var value = PreProcessResolver(info, resolver);
|
|
||||||
return (ref BuilderContext context) =>
|
|
||||||
{
|
|
||||||
info.SetValue(context.Existing, context.Resolve(info, context.Name, value));
|
|
||||||
return context.Existing;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
protected override Expression GetExpression(PropertyInfo property, string name, object resolver)
|
|
||||||
{
|
|
||||||
return Expression.Convert(
|
|
||||||
Expression.Call(BuilderContextExpression.Context, ResolveProperty,
|
|
||||||
Expression.Constant(property, typeof(PropertyInfo)),
|
|
||||||
Expression.Constant(name, typeof(string)),
|
|
||||||
Expression.Constant(PreProcessResolver(property, resolver), typeof(object))),
|
|
||||||
property.PropertyType);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected override MemberExpression CreateMemberExpression(PropertyInfo info)
|
|
||||||
=> Expression.Property(Expression.Convert(BuilderContextExpression.Existing, info.DeclaringType), info);
|
|
||||||
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
|
|
||||||
#region Parameter Resolver Factories
|
|
||||||
|
|
||||||
protected override ResolveDelegate<BuilderContext> DependencyResolverFactory(Attribute attribute, object info, object resolver, object defaultValue)
|
|
||||||
{
|
|
||||||
return (ref BuilderContext context) =>
|
|
||||||
{
|
|
||||||
((PropertyInfo)info).SetValue(context.Existing,
|
|
||||||
context.Resolve((PropertyInfo)info, ((DependencyResolutionAttribute)attribute).Name, resolver ?? DependencyAttribute.Instance));
|
|
||||||
|
|
||||||
return context.Existing;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
protected override ResolveDelegate<BuilderContext> OptionalDependencyResolverFactory(Attribute attribute, object info, object resolver, object defaultValue)
|
|
||||||
{
|
|
||||||
return (ref BuilderContext context) =>
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
((PropertyInfo)info).SetValue(context.Existing,
|
|
||||||
context.Resolve((PropertyInfo)info, ((DependencyResolutionAttribute)attribute).Name, resolver ?? OptionalDependencyAttribute.Instance));
|
|
||||||
return context.Existing;
|
|
||||||
}
|
|
||||||
catch
|
|
||||||
{
|
|
||||||
((PropertyInfo)info).SetValue(context.Existing, defaultValue);
|
|
||||||
return context.Existing;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
|
|
||||||
#region Implementation
|
|
||||||
|
|
||||||
public static IEnumerable<PropertyInfo> GetPropertiesHierarchical(Type type)
|
|
||||||
{
|
|
||||||
if (type == null)
|
|
||||||
{
|
|
||||||
return Enumerable.Empty<PropertyInfo>();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (type == typeof(object))
|
|
||||||
{
|
|
||||||
return type.GetTypeInfo().DeclaredProperties;
|
|
||||||
}
|
|
||||||
|
|
||||||
return type.GetTypeInfo()
|
|
||||||
.DeclaredProperties
|
|
||||||
.Concat(GetPropertiesHierarchical(type.GetTypeInfo().BaseType));
|
|
||||||
}
|
|
||||||
|
|
||||||
private object PreProcessResolver(PropertyInfo property, object resolver)
|
|
||||||
{
|
|
||||||
switch (resolver)
|
|
||||||
{
|
|
||||||
case IResolve policy:
|
|
||||||
return (ResolveDelegate<BuilderContext>)policy.Resolve;
|
|
||||||
|
|
||||||
case IResolverFactory factory:
|
|
||||||
return factory.GetResolver<BuilderContext>(property.PropertyType);
|
|
||||||
|
|
||||||
case Type type:
|
|
||||||
return typeof(Type) == property.PropertyType
|
|
||||||
? type : (object)property;
|
|
||||||
}
|
|
||||||
|
|
||||||
return resolver;
|
|
||||||
}
|
|
||||||
|
|
||||||
#endregion
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -0,0 +1,28 @@
|
||||||
|
using System.Linq.Expressions;
|
||||||
|
using System.Reflection;
|
||||||
|
using Unity.Builder;
|
||||||
|
|
||||||
|
namespace Unity.Processors
|
||||||
|
{
|
||||||
|
public partial class PropertyProcessor
|
||||||
|
{
|
||||||
|
|
||||||
|
|
||||||
|
#region Overrides
|
||||||
|
|
||||||
|
protected override Expression GetResolverExpression(PropertyInfo property, string name, object resolver)
|
||||||
|
{
|
||||||
|
return Expression.Convert(
|
||||||
|
Expression.Call(BuilderContextExpression.Context, ResolveProperty,
|
||||||
|
Expression.Constant(property, typeof(PropertyInfo)),
|
||||||
|
Expression.Constant(name, typeof(string)),
|
||||||
|
Expression.Constant(PreProcessResolver(property, resolver), typeof(object))),
|
||||||
|
property.PropertyType);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override MemberExpression CreateMemberExpression(PropertyInfo info)
|
||||||
|
=> Expression.Property(Expression.Convert(BuilderContextExpression.Existing, info.DeclaringType), info);
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,90 @@
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Reflection;
|
||||||
|
using Unity.Builder;
|
||||||
|
using Unity.Policy;
|
||||||
|
|
||||||
|
namespace Unity.Processors
|
||||||
|
{
|
||||||
|
public partial class PropertyProcessor : MemberProcessor<PropertyInfo, object>
|
||||||
|
{
|
||||||
|
#region Fields
|
||||||
|
|
||||||
|
public static readonly MethodInfo ResolveProperty =
|
||||||
|
typeof(BuilderContext).GetTypeInfo()
|
||||||
|
.GetDeclaredMethods(nameof(BuilderContext.Resolve))
|
||||||
|
.First(m =>
|
||||||
|
{
|
||||||
|
var parameters = m.GetParameters();
|
||||||
|
return 2 <= parameters.Length &&
|
||||||
|
typeof(PropertyInfo) == parameters[0].ParameterType;
|
||||||
|
});
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
|
||||||
|
#region Constructors
|
||||||
|
|
||||||
|
public PropertyProcessor(IPolicySet policySet)
|
||||||
|
: base(policySet)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
|
||||||
|
#region Overrides
|
||||||
|
|
||||||
|
protected override Type MemberType(PropertyInfo info) => info.PropertyType;
|
||||||
|
|
||||||
|
protected override IEnumerable<PropertyInfo> DeclaredMembers(Type type)
|
||||||
|
{
|
||||||
|
#if NETSTANDARD1_0
|
||||||
|
return GetPropertiesHierarchical(type)
|
||||||
|
.Where(p =>
|
||||||
|
{
|
||||||
|
if (!p.CanWrite) return false;
|
||||||
|
|
||||||
|
var propertyMethod = p.GetSetMethod(true) ??
|
||||||
|
p.GetGetMethod(true);
|
||||||
|
|
||||||
|
// Skip static properties and indexers.
|
||||||
|
if (propertyMethod.IsStatic || p.GetIndexParameters().Length != 0)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
});
|
||||||
|
#else
|
||||||
|
return type.GetProperties(BindingFlags.Instance | BindingFlags.Public)
|
||||||
|
.Where(p => p.CanWrite && p.GetIndexParameters().Length == 0);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
|
||||||
|
#region Implementation
|
||||||
|
|
||||||
|
#if NETSTANDARD1_0
|
||||||
|
public static IEnumerable<PropertyInfo> GetPropertiesHierarchical(Type type)
|
||||||
|
{
|
||||||
|
if (type == null)
|
||||||
|
{
|
||||||
|
return Enumerable.Empty<PropertyInfo>();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (type == typeof(object))
|
||||||
|
{
|
||||||
|
return type.GetTypeInfo().DeclaredProperties;
|
||||||
|
}
|
||||||
|
|
||||||
|
return type.GetTypeInfo()
|
||||||
|
.DeclaredProperties
|
||||||
|
.Concat(GetPropertiesHierarchical(type.GetTypeInfo().BaseType));
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,60 @@
|
||||||
|
using System;
|
||||||
|
using System.Reflection;
|
||||||
|
using Unity.Builder;
|
||||||
|
using Unity.Policy;
|
||||||
|
|
||||||
|
namespace Unity.Processors
|
||||||
|
{
|
||||||
|
public partial class PropertyProcessor
|
||||||
|
{
|
||||||
|
|
||||||
|
|
||||||
|
#region Overrides
|
||||||
|
|
||||||
|
protected override ResolveDelegate<BuilderContext> GetResolverDelegate(PropertyInfo info, object resolver)
|
||||||
|
{
|
||||||
|
var value = PreProcessResolver(info, resolver);
|
||||||
|
return (ref BuilderContext context) =>
|
||||||
|
{
|
||||||
|
info.SetValue(context.Existing, context.Resolve(info, context.Name, value));
|
||||||
|
return context.Existing;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
|
||||||
|
#region Parameter Resolver Factories
|
||||||
|
|
||||||
|
protected override ResolveDelegate<BuilderContext> DependencyResolverFactory(Attribute attribute, object info, object resolver, object defaultValue)
|
||||||
|
{
|
||||||
|
return (ref BuilderContext context) =>
|
||||||
|
{
|
||||||
|
((PropertyInfo)info).SetValue(context.Existing,
|
||||||
|
context.Resolve((PropertyInfo)info, ((DependencyResolutionAttribute)attribute).Name, resolver ?? DependencyAttribute.Instance));
|
||||||
|
|
||||||
|
return context.Existing;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override ResolveDelegate<BuilderContext> OptionalDependencyResolverFactory(Attribute attribute, object info, object resolver, object defaultValue)
|
||||||
|
{
|
||||||
|
return (ref BuilderContext context) =>
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
((PropertyInfo)info).SetValue(context.Existing,
|
||||||
|
context.Resolve((PropertyInfo)info, ((DependencyResolutionAttribute)attribute).Name, resolver ?? OptionalDependencyAttribute.Instance));
|
||||||
|
return context.Existing;
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
((PropertyInfo)info).SetValue(context.Existing, defaultValue);
|
||||||
|
return context.Existing;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
}
|
||||||
|
}
|
|
@ -64,12 +64,12 @@ namespace Unity
|
||||||
|
|
||||||
// Processors
|
// Processors
|
||||||
var fieldsProcessor = new FieldsProcessor(Defaults);
|
var fieldsProcessor = new FieldsProcessor(Defaults);
|
||||||
var methodsProcessor = new MethodsProcessor(Defaults);
|
var methodsProcessor = new MethodProcessor(Defaults);
|
||||||
var propertiesProcessor = new PropertiesProcessor(Defaults);
|
var propertiesProcessor = new PropertyProcessor(Defaults);
|
||||||
var constructorProcessor = new ConstructorDiagnostic(Defaults, IsTypeExplicitlyRegistered);
|
var constructorProcessor = new ConstructorDiagnostic(Defaults, IsTypeExplicitlyRegistered);
|
||||||
|
|
||||||
// Processors chain
|
// Processors chain
|
||||||
_processors = new StagedStrategyChain<BuildMemberProcessor, BuilderStage>
|
_processors = new StagedStrategyChain<MemberProcessor, BuilderStage>
|
||||||
{
|
{
|
||||||
{ constructorProcessor, BuilderStage.Creation },
|
{ constructorProcessor, BuilderStage.Creation },
|
||||||
{ fieldsProcessor, BuilderStage.Fields },
|
{ fieldsProcessor, BuilderStage.Fields },
|
||||||
|
|
|
@ -43,11 +43,11 @@ namespace Unity
|
||||||
|
|
||||||
// Strategies
|
// Strategies
|
||||||
private StagedStrategyChain<BuilderStrategy, UnityBuildStage> _strategies;
|
private StagedStrategyChain<BuilderStrategy, UnityBuildStage> _strategies;
|
||||||
private StagedStrategyChain<BuildMemberProcessor, BuilderStage> _processors;
|
private StagedStrategyChain<MemberProcessor, BuilderStage> _processors;
|
||||||
|
|
||||||
// Caches
|
// Caches
|
||||||
private BuilderStrategy[] _strategiesChain;
|
private BuilderStrategy[] _strategiesChain;
|
||||||
private BuildMemberProcessor[] _processorsChain;
|
private MemberProcessor[] _processorsChain;
|
||||||
|
|
||||||
// Events
|
// Events
|
||||||
private event EventHandler<RegisterEventArgs> Registering;
|
private event EventHandler<RegisterEventArgs> Registering;
|
||||||
|
|
|
@ -39,12 +39,12 @@ namespace Unity
|
||||||
(ResolveDelegate<BuilderContext>)ExecuteDefaultPlan);
|
(ResolveDelegate<BuilderContext>)ExecuteDefaultPlan);
|
||||||
// Processors
|
// Processors
|
||||||
var fieldsProcessor = new FieldsProcessor(Defaults);
|
var fieldsProcessor = new FieldsProcessor(Defaults);
|
||||||
var methodsProcessor = new MethodsProcessor(Defaults);
|
var methodsProcessor = new MethodProcessor(Defaults);
|
||||||
var propertiesProcessor = new PropertiesProcessor(Defaults);
|
var propertiesProcessor = new PropertyProcessor(Defaults);
|
||||||
var constructorProcessor = new ConstructorProcessor(Defaults, IsTypeExplicitlyRegistered);
|
var constructorProcessor = new ConstructorProcessor(Defaults, IsTypeExplicitlyRegistered);
|
||||||
|
|
||||||
// Processors chain
|
// Processors chain
|
||||||
_processors = new StagedStrategyChain<BuildMemberProcessor, BuilderStage>
|
_processors = new StagedStrategyChain<MemberProcessor, BuilderStage>
|
||||||
{
|
{
|
||||||
{ constructorProcessor, BuilderStage.Creation },
|
{ constructorProcessor, BuilderStage.Creation },
|
||||||
{ fieldsProcessor, BuilderStage.Fields },
|
{ fieldsProcessor, BuilderStage.Fields },
|
||||||
|
|
|
@ -226,7 +226,7 @@ namespace Unity
|
||||||
var expressions = new List<Expression>();
|
var expressions = new List<Expression>();
|
||||||
foreach (var processor in chain)
|
foreach (var processor in chain)
|
||||||
{
|
{
|
||||||
foreach (var step in processor.GetBuildSteps(type, registration))
|
foreach (var step in processor.GetExpressions(type, registration))
|
||||||
expressions.Add(step);
|
expressions.Add(step);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -252,7 +252,7 @@ namespace Unity
|
||||||
|
|
||||||
foreach (var processor in _processorsChain)
|
foreach (var processor in _processorsChain)
|
||||||
{
|
{
|
||||||
foreach (var step in processor.GetBuildSteps(type, registration))
|
foreach (var step in processor.GetExpressions(type, registration))
|
||||||
expressions.Add(step);
|
expressions.Add(step);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Загрузка…
Ссылка в новой задаче