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
|
||||
|
||||
public override IEnumerable<Expression> GetBuildSteps(Type type, IPolicySet registration)
|
||||
public override IEnumerable<Expression> GetExpressions(Type type, IPolicySet registration)
|
||||
{
|
||||
// Validate if Type could be created
|
||||
var exceptionExpr = ValidateConstructedTypeExpression(type);
|
||||
|
@ -132,7 +132,7 @@ namespace Unity.Processors
|
|||
// Create 'new' expression
|
||||
var ifThenExpr = Expression.IfThen(
|
||||
Expression.Equal(Expression.Constant(null), BuilderContextExpression.Existing),
|
||||
BuildMemberExpression(info, resolvers));
|
||||
ExpressionFromMemberInfo(info, resolvers));
|
||||
|
||||
// Check if PerResolveLifetimeManager is required
|
||||
return lifetimeManager is PerResolveLifetimeManager
|
||||
|
@ -140,7 +140,7 @@ namespace Unity.Processors
|
|||
: new Expression[] { ifThenExpr };
|
||||
}
|
||||
|
||||
protected override Expression BuildMemberExpression(ConstructorInfo info, object[] resolvers)
|
||||
protected override Expression ExpressionFromMemberInfo(ConstructorInfo info, object[] resolvers)
|
||||
{
|
||||
// Check if had ByRef parameters
|
||||
var parameters = info.GetParameters();
|
||||
|
|
|
@ -53,7 +53,7 @@ namespace Unity.Processors
|
|||
|
||||
#region Overrides
|
||||
|
||||
public override IEnumerable<Expression> GetBuildSteps(Type type, IPolicySet registration)
|
||||
public override IEnumerable<Expression> GetExpressions(Type type, IPolicySet registration)
|
||||
{
|
||||
// Select ConstructorInfo
|
||||
var selector = GetPolicy<ISelect<ConstructorInfo>>(registration);
|
||||
|
|
|
@ -5,10 +5,11 @@ using System.Linq;
|
|||
using System.Reflection;
|
||||
using Unity.Injection;
|
||||
using Unity.Policy;
|
||||
using Unity.Registration;
|
||||
|
||||
namespace Unity.Processors
|
||||
{
|
||||
public partial class ConstructorProcessor : MethodBaseInfoProcessor<ConstructorInfo>
|
||||
public partial class ConstructorProcessor : MethodBaseProcessor<ConstructorInfo>
|
||||
{
|
||||
#region Fields
|
||||
|
||||
|
@ -39,6 +40,41 @@ namespace Unity.Processors
|
|||
|
||||
#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)
|
||||
{
|
||||
#if NETSTANDARD1_0
|
||||
|
@ -50,51 +86,6 @@ namespace Unity.Processors
|
|||
#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
|
||||
|
||||
|
|
@ -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.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Linq.Expressions;
|
||||
using System.Reflection;
|
||||
using Unity.Builder;
|
||||
using Unity.Policy;
|
||||
using Unity.Storage;
|
||||
|
||||
namespace Unity.Processors
|
||||
{
|
||||
public class FieldsProcessor : BuildMemberProcessor<FieldInfo, object>
|
||||
public partial class FieldsProcessor : MemberProcessor<FieldInfo, object>
|
||||
{
|
||||
#region Fields
|
||||
|
||||
|
@ -50,67 +48,11 @@ namespace Unity.Processors
|
|||
|
||||
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
|
||||
|
||||
|
||||
#region Implementation
|
||||
#if NETSTANDARD1_0
|
||||
|
||||
public static IEnumerable<FieldInfo> GetFieldsHierarchical(Type type)
|
||||
{
|
||||
|
@ -128,25 +70,7 @@ namespace Unity.Processors
|
|||
.DeclaredFields
|
||||
.Concat(GetFieldsHierarchical(type.GetTypeInfo().BaseType));
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
#endif
|
||||
#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
|
||||
var fieldsProcessor = new FieldsProcessor(Defaults);
|
||||
var methodsProcessor = new MethodsProcessor(Defaults);
|
||||
var propertiesProcessor = new PropertiesProcessor(Defaults);
|
||||
var methodsProcessor = new MethodProcessor(Defaults);
|
||||
var propertiesProcessor = new PropertyProcessor(Defaults);
|
||||
var constructorProcessor = new ConstructorDiagnostic(Defaults, IsTypeExplicitlyRegistered);
|
||||
|
||||
// Processors chain
|
||||
_processors = new StagedStrategyChain<BuildMemberProcessor, BuilderStage>
|
||||
_processors = new StagedStrategyChain<MemberProcessor, BuilderStage>
|
||||
{
|
||||
{ constructorProcessor, BuilderStage.Creation },
|
||||
{ fieldsProcessor, BuilderStage.Fields },
|
||||
|
|
|
@ -43,11 +43,11 @@ namespace Unity
|
|||
|
||||
// Strategies
|
||||
private StagedStrategyChain<BuilderStrategy, UnityBuildStage> _strategies;
|
||||
private StagedStrategyChain<BuildMemberProcessor, BuilderStage> _processors;
|
||||
private StagedStrategyChain<MemberProcessor, BuilderStage> _processors;
|
||||
|
||||
// Caches
|
||||
private BuilderStrategy[] _strategiesChain;
|
||||
private BuildMemberProcessor[] _processorsChain;
|
||||
private MemberProcessor[] _processorsChain;
|
||||
|
||||
// Events
|
||||
private event EventHandler<RegisterEventArgs> Registering;
|
||||
|
|
|
@ -39,12 +39,12 @@ namespace Unity
|
|||
(ResolveDelegate<BuilderContext>)ExecuteDefaultPlan);
|
||||
// Processors
|
||||
var fieldsProcessor = new FieldsProcessor(Defaults);
|
||||
var methodsProcessor = new MethodsProcessor(Defaults);
|
||||
var propertiesProcessor = new PropertiesProcessor(Defaults);
|
||||
var methodsProcessor = new MethodProcessor(Defaults);
|
||||
var propertiesProcessor = new PropertyProcessor(Defaults);
|
||||
var constructorProcessor = new ConstructorProcessor(Defaults, IsTypeExplicitlyRegistered);
|
||||
|
||||
// Processors chain
|
||||
_processors = new StagedStrategyChain<BuildMemberProcessor, BuilderStage>
|
||||
_processors = new StagedStrategyChain<MemberProcessor, BuilderStage>
|
||||
{
|
||||
{ constructorProcessor, BuilderStage.Creation },
|
||||
{ fieldsProcessor, BuilderStage.Fields },
|
||||
|
|
|
@ -226,7 +226,7 @@ namespace Unity
|
|||
var expressions = new List<Expression>();
|
||||
foreach (var processor in chain)
|
||||
{
|
||||
foreach (var step in processor.GetBuildSteps(type, registration))
|
||||
foreach (var step in processor.GetExpressions(type, registration))
|
||||
expressions.Add(step);
|
||||
}
|
||||
|
||||
|
@ -252,7 +252,7 @@ namespace Unity
|
|||
|
||||
foreach (var processor in _processorsChain)
|
||||
{
|
||||
foreach (var step in processor.GetBuildSteps(type, registration))
|
||||
foreach (var step in processor.GetExpressions(type, registration))
|
||||
expressions.Add(step);
|
||||
}
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче