Refactoring
This commit is contained in:
Родитель
92285ea874
Коммит
b6f43256bf
|
@ -1,67 +0,0 @@
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Linq.Expressions;
|
|
||||||
using System.Reflection;
|
|
||||||
using Unity.Policy;
|
|
||||||
using Unity.Storage;
|
|
||||||
using Unity.Strategies;
|
|
||||||
|
|
||||||
namespace Unity.Builder
|
|
||||||
{
|
|
||||||
public class CompiledStrategy<TMemberInfo, TData> : BuilderStrategy,
|
|
||||||
IStagedStrategyChain<Converter<Type, (TMemberInfo, TData)>, SelectionStage>
|
|
||||||
where TMemberInfo : MemberInfo
|
|
||||||
{
|
|
||||||
#region Fields
|
|
||||||
|
|
||||||
private readonly List<Converter<Type, (TMemberInfo, TData)>>[] _stages;
|
|
||||||
private Converter<Type, (TMemberInfo, TData)>[] _cache;
|
|
||||||
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
|
|
||||||
#region Constructors
|
|
||||||
|
|
||||||
public CompiledStrategy(params (Converter<Type, (TMemberInfo, TData)>, SelectionStage)[] arguments)
|
|
||||||
{
|
|
||||||
var length = Enum.GetValues(typeof(SelectionStage)).Length;
|
|
||||||
_stages = new List<Converter<Type, (TMemberInfo, TData)>>[length];
|
|
||||||
for (var i = 0; i < length; i++)
|
|
||||||
{
|
|
||||||
_stages[i] = new List<Converter<Type, (TMemberInfo, TData)>>();
|
|
||||||
}
|
|
||||||
|
|
||||||
foreach (var tuple in arguments)
|
|
||||||
{
|
|
||||||
_stages[Convert.ToInt32(tuple.Item2)].Add(tuple.Item1);
|
|
||||||
}
|
|
||||||
|
|
||||||
_cache = _stages.SelectMany(s => s).ToArray();
|
|
||||||
}
|
|
||||||
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
|
|
||||||
#region IStagedStrategyChain
|
|
||||||
|
|
||||||
public void Add(Converter<Type, (TMemberInfo, TData)> strategy, SelectionStage stage)
|
|
||||||
{
|
|
||||||
lock (_stages)
|
|
||||||
{
|
|
||||||
_stages[Convert.ToInt32(stage)].Add(strategy);
|
|
||||||
_cache = _stages.SelectMany(s => s).ToArray();
|
|
||||||
Invalidated?.Invoke(this, new EventArgs());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
|
|
||||||
#region Event
|
|
||||||
|
|
||||||
public event EventHandler<EventArgs> Invalidated;
|
|
||||||
|
|
||||||
#endregion
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,12 +1,12 @@
|
||||||
using System;
|
using System;
|
||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
using System.Linq.Expressions;
|
|
||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
using System.Security;
|
using System.Security;
|
||||||
using Unity.Policy;
|
using Unity.Policy;
|
||||||
using Unity.Registration;
|
using Unity.Registration;
|
||||||
using Unity.Resolution;
|
using Unity.Resolution;
|
||||||
using Unity.Storage;
|
using Unity.Storage;
|
||||||
|
using Unity.Strategies;
|
||||||
|
|
||||||
namespace Unity.Builder
|
namespace Unity.Builder
|
||||||
{
|
{
|
||||||
|
@ -73,7 +73,7 @@ namespace Unity.Builder
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
|
|
||||||
#region Public Members
|
#region Public Properties
|
||||||
|
|
||||||
public object Existing { get; set; }
|
public object Existing { get; set; }
|
||||||
|
|
||||||
|
@ -85,8 +85,6 @@ namespace Unity.Builder
|
||||||
|
|
||||||
public Type DeclaringType { get; private set; }
|
public Type DeclaringType { get; private set; }
|
||||||
|
|
||||||
public ParameterExpression Variable;
|
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
|
|
||||||
|
@ -107,7 +105,7 @@ namespace Unity.Builder
|
||||||
DeclaringType = RegistrationType
|
DeclaringType = RegistrationType
|
||||||
};
|
};
|
||||||
|
|
||||||
return registration.BuildChain.ExecuteReThrowingPlan(ref context);
|
return ExecuteReThrowingPlan(registration.BuildChain, ref context);
|
||||||
}
|
}
|
||||||
|
|
||||||
public object Resolve(ParameterInfo parameter, string name, object value)
|
public object Resolve(ParameterInfo parameter, string name, object value)
|
||||||
|
@ -278,5 +276,36 @@ namespace Unity.Builder
|
||||||
}
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
|
|
||||||
|
#region Implementation
|
||||||
|
|
||||||
|
|
||||||
|
private static object ExecuteReThrowingPlan(BuilderStrategy[] chain, ref BuilderContext context)
|
||||||
|
{
|
||||||
|
var i = -1;
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
while (!context.BuildComplete && ++i < chain.Length)
|
||||||
|
{
|
||||||
|
chain[i].PreBuildUp(ref context);
|
||||||
|
}
|
||||||
|
|
||||||
|
while (--i >= 0)
|
||||||
|
{
|
||||||
|
chain[i].PostBuildUp(ref context);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
context.RequiresRecovery?.Recover();
|
||||||
|
throw;
|
||||||
|
}
|
||||||
|
|
||||||
|
return context.Existing;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,29 @@
|
||||||
|
using System.Linq;
|
||||||
|
using System.Linq.Expressions;
|
||||||
|
using System.Reflection;
|
||||||
|
using Unity.Resolution;
|
||||||
|
|
||||||
|
namespace Unity.Builder
|
||||||
|
{
|
||||||
|
public class BuilderContextExpression : IResolveContextExpression<BuilderContext>
|
||||||
|
{
|
||||||
|
#region Constructor
|
||||||
|
|
||||||
|
static BuilderContextExpression()
|
||||||
|
{
|
||||||
|
var typeInfo = typeof(BuilderContext).GetTypeInfo();
|
||||||
|
|
||||||
|
|
||||||
|
Existing = Expression.MakeMemberAccess(Context, typeInfo.GetDeclaredProperty(nameof(BuilderContext.Existing)));
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
|
||||||
|
#region Public Properties
|
||||||
|
|
||||||
|
public static readonly MemberExpression Existing;
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,110 +0,0 @@
|
||||||
using System.Linq;
|
|
||||||
using System.Linq.Expressions;
|
|
||||||
using System.Reflection;
|
|
||||||
using Unity.Container.Lifetime;
|
|
||||||
using Unity.Resolution;
|
|
||||||
|
|
||||||
namespace Unity.Builder.Expressions
|
|
||||||
{
|
|
||||||
public class BuilderContextExpression : IResolveContextExpression<BuilderContext>
|
|
||||||
{
|
|
||||||
#region Fields
|
|
||||||
|
|
||||||
private static ConstructorInfo _perResolveInfo = typeof(InternalPerResolveLifetimeManager)
|
|
||||||
.GetTypeInfo().DeclaredConstructors.First();
|
|
||||||
|
|
||||||
|
|
||||||
private static readonly MethodInfo _resolveField =
|
|
||||||
typeof(BuilderContext).GetTypeInfo()
|
|
||||||
.GetDeclaredMethods(nameof(BuilderContext.Resolve))
|
|
||||||
.First(m =>
|
|
||||||
{
|
|
||||||
var parameters = m.GetParameters();
|
|
||||||
return 2 <= parameters.Length &&
|
|
||||||
typeof(FieldInfo) == parameters[0].ParameterType;
|
|
||||||
});
|
|
||||||
|
|
||||||
private 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;
|
|
||||||
});
|
|
||||||
|
|
||||||
private static 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 Constructor
|
|
||||||
|
|
||||||
static BuilderContextExpression()
|
|
||||||
{
|
|
||||||
var typeInfo = typeof(BuilderContext).GetTypeInfo();
|
|
||||||
|
|
||||||
|
|
||||||
Existing = Expression.MakeMemberAccess(Context, typeInfo.GetDeclaredProperty(nameof(BuilderContext.Existing)));
|
|
||||||
}
|
|
||||||
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
|
|
||||||
#region Public Properties
|
|
||||||
|
|
||||||
public static readonly MemberExpression Existing;
|
|
||||||
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
|
|
||||||
#region Methods
|
|
||||||
|
|
||||||
public static Expression Resolve(FieldInfo field, string name, object resolver = null)
|
|
||||||
{
|
|
||||||
return Expression.Convert(
|
|
||||||
Expression.Call(Context, _resolveField,
|
|
||||||
Expression.Constant(field, typeof(FieldInfo)),
|
|
||||||
Expression.Constant(name, typeof(string)),
|
|
||||||
Expression.Constant(resolver, typeof(object))),
|
|
||||||
field.FieldType);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static Expression Resolve(PropertyInfo property, string name, object resolver = null)
|
|
||||||
{
|
|
||||||
return Expression.Convert(
|
|
||||||
Expression.Call(Context, _resolveProperty,
|
|
||||||
Expression.Constant(property, typeof(PropertyInfo)),
|
|
||||||
Expression.Constant(name, typeof(string)),
|
|
||||||
Expression.Constant(resolver, typeof(object))),
|
|
||||||
property.PropertyType);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static Expression Resolve(ParameterInfo parameter, string name, object resolver = null)
|
|
||||||
{
|
|
||||||
return Expression.Convert(
|
|
||||||
Expression.Call(Context, _resolveParameter,
|
|
||||||
Expression.Constant(parameter, typeof(ParameterInfo)),
|
|
||||||
Expression.Constant(name, typeof(string)),
|
|
||||||
Expression.Constant(resolver, typeof(object))),
|
|
||||||
parameter.ParameterType);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static Expression SetPerBuildSingleton(ref BuilderContext context)
|
|
||||||
{
|
|
||||||
return Set(context.RegistrationType, context.RegistrationName, typeof(LifetimeManager),
|
|
||||||
Expression.New(_perResolveInfo, context.Variable));
|
|
||||||
}
|
|
||||||
|
|
||||||
#endregion
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,21 +0,0 @@
|
||||||
using System;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Reflection;
|
|
||||||
|
|
||||||
namespace Unity.Builder.Expressions
|
|
||||||
{
|
|
||||||
public class ExceptionExpression
|
|
||||||
{
|
|
||||||
public static readonly ConstructorInfo InvalidOperationExceptionCtor =
|
|
||||||
typeof(InvalidOperationException)
|
|
||||||
.GetTypeInfo()
|
|
||||||
.DeclaredConstructors
|
|
||||||
.First(c =>
|
|
||||||
{
|
|
||||||
var parameters = c.GetParameters();
|
|
||||||
return 2 == parameters.Length &&
|
|
||||||
typeof(string) == parameters[0].ParameterType &&
|
|
||||||
typeof(Exception) == parameters[1].ParameterType;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,78 +0,0 @@
|
||||||
using System;
|
|
||||||
using Unity.Strategies;
|
|
||||||
|
|
||||||
namespace Unity.Builder
|
|
||||||
{
|
|
||||||
public static class PlanExtension
|
|
||||||
{
|
|
||||||
public static object ExecutePlan(this BuilderStrategy[] chain, ref BuilderContext context)
|
|
||||||
{
|
|
||||||
var i = -1;
|
|
||||||
|
|
||||||
while (!context.BuildComplete && ++i < chain.Length)
|
|
||||||
{
|
|
||||||
chain[i].PreBuildUp(ref context);
|
|
||||||
}
|
|
||||||
|
|
||||||
while (--i >= 0)
|
|
||||||
{
|
|
||||||
chain[i].PostBuildUp(ref context);
|
|
||||||
}
|
|
||||||
|
|
||||||
return context.Existing;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static object ExecuteThrowingPlan(this BuilderStrategy[] chain, ref BuilderContext context)
|
|
||||||
{
|
|
||||||
var i = -1;
|
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
while (!context.BuildComplete && ++i < chain.Length)
|
|
||||||
{
|
|
||||||
chain[i].PreBuildUp(ref context);
|
|
||||||
}
|
|
||||||
|
|
||||||
while (--i >= 0)
|
|
||||||
{
|
|
||||||
chain[i].PostBuildUp(ref context);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
context.RequiresRecovery?.Recover();
|
|
||||||
// TODO: 5.9.0 Add proper error message
|
|
||||||
throw new ResolutionFailedException(context.RegistrationType,
|
|
||||||
context.RegistrationName,
|
|
||||||
"", ex);
|
|
||||||
}
|
|
||||||
|
|
||||||
return context.Existing;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static object ExecuteReThrowingPlan(this BuilderStrategy[] chain, ref BuilderContext context)
|
|
||||||
{
|
|
||||||
var i = -1;
|
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
while (!context.BuildComplete && ++i < chain.Length)
|
|
||||||
{
|
|
||||||
chain[i].PreBuildUp(ref context);
|
|
||||||
}
|
|
||||||
|
|
||||||
while (--i >= 0)
|
|
||||||
{
|
|
||||||
chain[i].PostBuildUp(ref context);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch
|
|
||||||
{
|
|
||||||
context.RequiresRecovery?.Recover();
|
|
||||||
throw;
|
|
||||||
}
|
|
||||||
|
|
||||||
return context.Existing;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -4,9 +4,7 @@ using System.Linq;
|
||||||
using System.Linq.Expressions;
|
using System.Linq.Expressions;
|
||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
using Unity.Builder;
|
using Unity.Builder;
|
||||||
using Unity.Builder.Expressions;
|
|
||||||
using Unity.Policy;
|
using Unity.Policy;
|
||||||
using Unity.Resolution;
|
|
||||||
|
|
||||||
namespace Unity.ObjectBuilder.BuildPlan.DynamicMethod
|
namespace Unity.ObjectBuilder.BuildPlan.DynamicMethod
|
||||||
{
|
{
|
||||||
|
|
|
@ -14,7 +14,28 @@ namespace Unity.Processors
|
||||||
|
|
||||||
public abstract class MemberBuildProcessor
|
public abstract class MemberBuildProcessor
|
||||||
{
|
{
|
||||||
|
#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> GetEnumerator(ref BuilderContext context);
|
public abstract IEnumerable<Expression> GetEnumerator(ref BuilderContext context);
|
||||||
|
|
||||||
|
#endregion
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -23,18 +44,6 @@ namespace Unity.Processors
|
||||||
{
|
{
|
||||||
#region Fields
|
#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));
|
|
||||||
|
|
||||||
protected (Type type, MemberExpressionFactory factory)[] ResolverFactories;
|
protected (Type type, MemberExpressionFactory factory)[] ResolverFactories;
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
@ -79,7 +88,7 @@ namespace Unity.Processors
|
||||||
|
|
||||||
#region Public Methods
|
#region Public Methods
|
||||||
|
|
||||||
public virtual void Add(Type type, MemberExpressionFactory factory)
|
public void Add(Type type, MemberExpressionFactory factory)
|
||||||
{
|
{
|
||||||
for (var i = 0; i < ResolverFactories.Length; i++)
|
for (var i = 0; i < ResolverFactories.Length; i++)
|
||||||
{
|
{
|
||||||
|
@ -104,7 +113,7 @@ namespace Unity.Processors
|
||||||
{
|
{
|
||||||
var selector = GetPolicy<ISelect<TMemberInfo>>(ref context, context.RegistrationType, context.RegistrationName);
|
var selector = GetPolicy<ISelect<TMemberInfo>>(ref context, context.RegistrationType, context.RegistrationName);
|
||||||
var members = selector.Select(ref context);
|
var members = selector.Select(ref context);
|
||||||
return GetEnumerator(context.Type, context.Name, context.Variable, members);
|
return GetEnumerator(context.Type, context.Name, members);
|
||||||
}
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
@ -112,7 +121,7 @@ namespace Unity.Processors
|
||||||
|
|
||||||
#region Expression Building
|
#region Expression Building
|
||||||
|
|
||||||
protected virtual IEnumerable<Expression> GetEnumerator(Type type, string name, ParameterExpression variable, IEnumerable<object> members)
|
protected virtual IEnumerable<Expression> GetEnumerator(Type type, string name, IEnumerable<object> members)
|
||||||
{
|
{
|
||||||
foreach (var member in members)
|
foreach (var member in members)
|
||||||
{
|
{
|
||||||
|
@ -121,13 +130,13 @@ namespace Unity.Processors
|
||||||
switch (member)
|
switch (member)
|
||||||
{
|
{
|
||||||
case TMemberInfo memberInfo:
|
case TMemberInfo memberInfo:
|
||||||
memberExpr = CreateMemberExpression(variable, memberInfo);
|
memberExpr = CreateMemberExpression(memberInfo);
|
||||||
yield return BuildMemberExpression(memberExpr, memberInfo, name, null);
|
yield return BuildMemberExpression(memberExpr, memberInfo, name, null);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case InjectionMember<TMemberInfo, TData> injectionMember:
|
case InjectionMember<TMemberInfo, TData> injectionMember:
|
||||||
var (info, value) = injectionMember.FromType(type);
|
var (info, value) = injectionMember.FromType(type);
|
||||||
memberExpr = CreateMemberExpression(variable, info);
|
memberExpr = CreateMemberExpression(info);
|
||||||
yield return BuildMemberExpression(memberExpr, info, name, value);
|
yield return BuildMemberExpression(memberExpr, info, name, value);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -169,7 +178,7 @@ namespace Unity.Processors
|
||||||
protected virtual Expression ResolveExpression(TMemberInfo info, string name, object resolver)
|
protected virtual Expression ResolveExpression(TMemberInfo info, string name, object resolver)
|
||||||
=> throw new NotImplementedException();
|
=> throw new NotImplementedException();
|
||||||
|
|
||||||
protected virtual MemberExpression CreateMemberExpression(ParameterExpression variable, TMemberInfo info)
|
protected virtual MemberExpression CreateMemberExpression(TMemberInfo info)
|
||||||
=> throw new NotImplementedException();
|
=> throw new NotImplementedException();
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
|
@ -1,8 +1,9 @@
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
using System.Linq.Expressions;
|
using System.Linq.Expressions;
|
||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
using Unity.Builder.Expressions;
|
using Unity.Builder;
|
||||||
using Unity.Injection;
|
using Unity.Injection;
|
||||||
|
|
||||||
namespace Unity.Processors
|
namespace Unity.Processors
|
||||||
|
@ -10,6 +11,21 @@ namespace Unity.Processors
|
||||||
public abstract class MethodBaseInfoProcessor<TMemberInfo> : MemberBuildProcessor<TMemberInfo, object[]>
|
public abstract class MethodBaseInfoProcessor<TMemberInfo> : MemberBuildProcessor<TMemberInfo, object[]>
|
||||||
where TMemberInfo : MethodBase
|
where TMemberInfo : MethodBase
|
||||||
{
|
{
|
||||||
|
#region Fields
|
||||||
|
|
||||||
|
private static 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
|
#region Constructors
|
||||||
|
|
||||||
public MethodBaseInfoProcessor(Type attribute)
|
public MethodBaseInfoProcessor(Type attribute)
|
||||||
|
@ -27,7 +43,7 @@ namespace Unity.Processors
|
||||||
|
|
||||||
protected override Type MemberType(TMemberInfo info) => info.DeclaringType;
|
protected override Type MemberType(TMemberInfo info) => info.DeclaringType;
|
||||||
|
|
||||||
protected override IEnumerable<Expression> GetEnumerator(Type type, string name, ParameterExpression variable, IEnumerable<object> members)
|
protected override IEnumerable<Expression> GetEnumerator(Type type, string name, IEnumerable<object> members)
|
||||||
{
|
{
|
||||||
foreach (var member in members)
|
foreach (var member in members)
|
||||||
{
|
{
|
||||||
|
@ -35,13 +51,13 @@ namespace Unity.Processors
|
||||||
{
|
{
|
||||||
case TMemberInfo memberInfo:
|
case TMemberInfo memberInfo:
|
||||||
yield return ValidateMemberInfo(memberInfo) ??
|
yield return ValidateMemberInfo(memberInfo) ??
|
||||||
CreateExpression(memberInfo, null, variable);
|
CreateExpression(memberInfo, null);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case MethodBaseMember<TMemberInfo> injectionMember:
|
case MethodBaseMember<TMemberInfo> injectionMember:
|
||||||
var (info, resolvers) = injectionMember.FromType(type);
|
var (info, resolvers) = injectionMember.FromType(type);
|
||||||
yield return ValidateMemberInfo(info) ??
|
yield return ValidateMemberInfo(info) ??
|
||||||
CreateExpression(info, resolvers, variable);
|
CreateExpression(info, resolvers);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
|
@ -76,12 +92,12 @@ namespace Unity.Processors
|
||||||
if (null == defaultValueExpr)
|
if (null == defaultValueExpr)
|
||||||
{
|
{
|
||||||
// Plain vanilla case
|
// Plain vanilla case
|
||||||
expression = BuilderContextExpression.Resolve(parameter, null, resolver);
|
expression = ResolveExpression(parameter, null, resolver);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
var variable = Expression.Variable(parameter.ParameterType);
|
var variable = Expression.Variable(parameter.ParameterType);
|
||||||
var resolve = BuilderContextExpression.Resolve(parameter, null, resolver);
|
var resolve = ResolveExpression(parameter, null, resolver);
|
||||||
|
|
||||||
expression = Expression.Block(new[] { variable }, new Expression[]
|
expression = Expression.Block(new[] { variable }, new Expression[]
|
||||||
{
|
{
|
||||||
|
@ -121,7 +137,7 @@ namespace Unity.Processors
|
||||||
if (null == member)
|
if (null == member)
|
||||||
{
|
{
|
||||||
// Plain vanilla case
|
// Plain vanilla case
|
||||||
return BuilderContextExpression.Resolve(parameter, ((DependencyResolutionAttribute)attribute).Name, resolver);
|
return ResolveExpression(parameter, ((DependencyResolutionAttribute)attribute).Name, resolver);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -133,7 +149,7 @@ namespace Unity.Processors
|
||||||
Expression.TryCatch(
|
Expression.TryCatch(
|
||||||
Expression.Assign(
|
Expression.Assign(
|
||||||
variable,
|
variable,
|
||||||
BuilderContextExpression.Resolve(parameter, ((DependencyResolutionAttribute)attribute).Name, resolver)),
|
ResolveExpression(parameter, ((DependencyResolutionAttribute)attribute).Name, resolver)),
|
||||||
Expression.Catch(typeof(Exception),
|
Expression.Catch(typeof(Exception),
|
||||||
Expression.Assign(variable, member))),
|
Expression.Assign(variable, member))),
|
||||||
variable
|
variable
|
||||||
|
@ -153,7 +169,7 @@ namespace Unity.Processors
|
||||||
Expression.TryCatch(
|
Expression.TryCatch(
|
||||||
Expression.Assign(
|
Expression.Assign(
|
||||||
variable,
|
variable,
|
||||||
BuilderContextExpression.Resolve(parameter, ((DependencyResolutionAttribute)attribute).Name, resolver)),
|
ResolveExpression(parameter, ((DependencyResolutionAttribute)attribute).Name, resolver)),
|
||||||
Expression.Catch(typeof(Exception),
|
Expression.Catch(typeof(Exception),
|
||||||
Expression.Assign(variable, member ?? Expression.Constant(null, parameter.ParameterType)))),
|
Expression.Assign(variable, member ?? Expression.Constant(null, parameter.ParameterType)))),
|
||||||
variable
|
variable
|
||||||
|
@ -166,7 +182,17 @@ namespace Unity.Processors
|
||||||
|
|
||||||
#region Implementation
|
#region Implementation
|
||||||
|
|
||||||
protected abstract Expression CreateExpression(TMemberInfo info, object[] resolvers, ParameterExpression variable);
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected abstract Expression CreateExpression(TMemberInfo info, object[] resolvers);
|
||||||
|
|
||||||
protected virtual Expression ValidateMemberInfo(TMemberInfo info) => null;
|
protected virtual Expression ValidateMemberInfo(TMemberInfo info) => null;
|
||||||
|
|
||||||
|
|
|
@ -5,10 +5,7 @@ using System.Linq;
|
||||||
using System.Linq.Expressions;
|
using System.Linq.Expressions;
|
||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
using Unity.Builder;
|
using Unity.Builder;
|
||||||
using Unity.Builder.Expressions;
|
|
||||||
using Unity.Container.Lifetime;
|
using Unity.Container.Lifetime;
|
||||||
using Unity.Injection;
|
|
||||||
using Unity.Policy;
|
|
||||||
|
|
||||||
namespace Unity.Processors
|
namespace Unity.Processors
|
||||||
{
|
{
|
||||||
|
@ -18,6 +15,29 @@ namespace Unity.Processors
|
||||||
|
|
||||||
private static readonly ConstructorLengthComparer ConstructorComparer = new ConstructorLengthComparer();
|
private static readonly ConstructorLengthComparer ConstructorComparer = new ConstructorLengthComparer();
|
||||||
|
|
||||||
|
private static readonly ConstructorInfo PerResolveInfo = typeof(InternalPerResolveLifetimeManager)
|
||||||
|
.GetTypeInfo().DeclaredConstructors.First();
|
||||||
|
|
||||||
|
private static readonly ConstructorInfo InvalidOperationExceptionCtor =
|
||||||
|
typeof(InvalidOperationException)
|
||||||
|
.GetTypeInfo()
|
||||||
|
.DeclaredConstructors
|
||||||
|
.First(c =>
|
||||||
|
{
|
||||||
|
var parameters = c.GetParameters();
|
||||||
|
return 2 == parameters.Length &&
|
||||||
|
typeof(string) == parameters[0].ParameterType &&
|
||||||
|
typeof(Exception) == parameters[1].ParameterType;
|
||||||
|
});
|
||||||
|
|
||||||
|
private static readonly Expression NoConstructorExceptionExpr =
|
||||||
|
Expression.Throw(
|
||||||
|
Expression.New(InvalidOperationExceptionCtor,
|
||||||
|
Expression.Call(StringFormat,
|
||||||
|
Expression.Constant("No public constructor is available for type {0}."),
|
||||||
|
BuilderContextExpression.Type),
|
||||||
|
InvalidRegistrationExpression));
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
|
|
||||||
|
@ -97,31 +117,20 @@ namespace Unity.Processors
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var expression = base.GetEnumerator(ref context)
|
var newExpr = base.GetEnumerator(ref context)
|
||||||
.FirstOrDefault();
|
.FirstOrDefault() ??
|
||||||
switch (expression)
|
NoConstructorExceptionExpr;
|
||||||
{
|
|
||||||
case NewExpression newExpression:
|
|
||||||
expression = Expression.Assign(context.Variable, newExpression);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case null:
|
var IfThenExpr = Expression.IfThen(Expression.Equal(Expression.Constant(null), BuilderContextExpression.Existing),
|
||||||
expression = Expression.Throw(
|
ValidateConstructedType(ref context) ?? newExpr);
|
||||||
Expression.New(ExceptionExpression.InvalidOperationExceptionCtor,
|
|
||||||
Expression.Call(StringFormat,
|
|
||||||
Expression.Constant("No public constructor is available for type {0}."),
|
|
||||||
BuilderContextExpression.Type),
|
|
||||||
InvalidRegistrationExpression));
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
var createExpr = Expression.IfThenElse(Expression.NotEqual(Expression.Constant(null), BuilderContextExpression.Existing),
|
|
||||||
Expression.Assign(context.Variable, Expression.Convert(BuilderContextExpression.Existing, context.Type)),
|
|
||||||
ValidateConstructedType(ref context) ?? expression);
|
|
||||||
|
|
||||||
return context.Registration.Get(typeof(LifetimeManager)) is PerResolveLifetimeManager
|
return context.Registration.Get(typeof(LifetimeManager)) is PerResolveLifetimeManager
|
||||||
? new Expression[] { createExpr, BuilderContextExpression.SetPerBuildSingleton(ref context) }
|
? new[] { IfThenExpr, BuilderContextExpression.Set(context.RegistrationType,
|
||||||
: new Expression[] { createExpr };
|
context.RegistrationName,
|
||||||
|
typeof(LifetimeManager),
|
||||||
|
Expression.New(PerResolveInfo,
|
||||||
|
BuilderContextExpression.Existing)) }
|
||||||
|
: new Expression[] { IfThenExpr };
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override Expression ValidateMemberInfo(ConstructorInfo info)
|
protected override Expression ValidateMemberInfo(ConstructorInfo info)
|
||||||
|
@ -129,7 +138,7 @@ namespace Unity.Processors
|
||||||
var parameters = info.GetParameters();
|
var parameters = info.GetParameters();
|
||||||
if (parameters.Any(pi => pi.ParameterType.IsByRef))
|
if (parameters.Any(pi => pi.ParameterType.IsByRef))
|
||||||
{
|
{
|
||||||
return Expression.Throw(Expression.New(ExceptionExpression.InvalidOperationExceptionCtor,
|
return Expression.Throw(Expression.New(InvalidOperationExceptionCtor,
|
||||||
Expression.Constant(CreateErrorMessage(Constants.SelectedConstructorHasRefParameters, info.DeclaringType, info)),
|
Expression.Constant(CreateErrorMessage(Constants.SelectedConstructorHasRefParameters, info.DeclaringType, info)),
|
||||||
InvalidRegistrationExpression));
|
InvalidRegistrationExpression));
|
||||||
}
|
}
|
||||||
|
@ -148,8 +157,15 @@ namespace Unity.Processors
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override Expression CreateExpression(ConstructorInfo info, object[] resolvers, ParameterExpression variable)
|
protected override Expression CreateExpression(ConstructorInfo info, object[] resolvers)
|
||||||
=> Expression.New(info, CreateParameterExpressions(info.GetParameters(), resolvers));
|
{
|
||||||
|
var variable = Expression.Variable(info.DeclaringType);
|
||||||
|
return Expression.Block(new[] { variable }, new Expression[]
|
||||||
|
{
|
||||||
|
Expression.Assign(variable, Expression.New(info, CreateParameterExpressions(info.GetParameters(), resolvers))),
|
||||||
|
Expression.Assign(BuilderContextExpression.Existing, Expression.Convert(variable, typeof(object)))
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
|
@ -166,7 +182,7 @@ namespace Unity.Processors
|
||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
return Expression.Throw(
|
return Expression.Throw(
|
||||||
Expression.New(ExceptionExpression.InvalidOperationExceptionCtor,
|
Expression.New(InvalidOperationExceptionCtor,
|
||||||
Expression.Call(
|
Expression.Call(
|
||||||
StringFormat,
|
StringFormat,
|
||||||
Expression.Constant(Constants.CannotConstructInterface),
|
Expression.Constant(Constants.CannotConstructInterface),
|
||||||
|
@ -181,7 +197,7 @@ namespace Unity.Processors
|
||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
return Expression.Throw(
|
return Expression.Throw(
|
||||||
Expression.New(ExceptionExpression.InvalidOperationExceptionCtor,
|
Expression.New(InvalidOperationExceptionCtor,
|
||||||
Expression.Call(
|
Expression.Call(
|
||||||
StringFormat,
|
StringFormat,
|
||||||
Expression.Constant(Constants.CannotConstructAbstractClass),
|
Expression.Constant(Constants.CannotConstructAbstractClass),
|
||||||
|
@ -196,7 +212,7 @@ namespace Unity.Processors
|
||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
return Expression.Throw(
|
return Expression.Throw(
|
||||||
Expression.New(ExceptionExpression.InvalidOperationExceptionCtor,
|
Expression.New(InvalidOperationExceptionCtor,
|
||||||
Expression.Call(
|
Expression.Call(
|
||||||
StringFormat,
|
StringFormat,
|
||||||
Expression.Constant(Constants.CannotConstructDelegate),
|
Expression.Constant(Constants.CannotConstructDelegate),
|
||||||
|
@ -207,7 +223,7 @@ namespace Unity.Processors
|
||||||
if (context.Type == typeof(string))
|
if (context.Type == typeof(string))
|
||||||
{
|
{
|
||||||
return Expression.Throw(
|
return Expression.Throw(
|
||||||
Expression.New(ExceptionExpression.InvalidOperationExceptionCtor,
|
Expression.New(InvalidOperationExceptionCtor,
|
||||||
Expression.Call(
|
Expression.Call(
|
||||||
StringFormat,
|
StringFormat,
|
||||||
Expression.Constant(Constants.TypeIsNotConstructable),
|
Expression.Constant(Constants.TypeIsNotConstructable),
|
||||||
|
|
|
@ -4,30 +4,51 @@ using System.Linq;
|
||||||
using System.Linq.Expressions;
|
using System.Linq.Expressions;
|
||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
using Unity.Builder;
|
using Unity.Builder;
|
||||||
using Unity.Builder.Expressions;
|
|
||||||
|
|
||||||
namespace Unity.Processors
|
namespace Unity.Processors
|
||||||
{
|
{
|
||||||
public class FieldsProcessor : MemberBuildProcessor<FieldInfo, object>
|
public class FieldsProcessor : MemberBuildProcessor<FieldInfo, object>
|
||||||
{
|
{
|
||||||
|
#region Fields
|
||||||
|
|
||||||
|
private static readonly MethodInfo ResolveField =
|
||||||
|
typeof(BuilderContext).GetTypeInfo()
|
||||||
|
.GetDeclaredMethods(nameof(BuilderContext.Resolve))
|
||||||
|
.First(m =>
|
||||||
|
{
|
||||||
|
var parameters = m.GetParameters();
|
||||||
|
return 2 <= parameters.Length &&
|
||||||
|
typeof(FieldInfo) == parameters[0].ParameterType;
|
||||||
|
});
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
|
||||||
#region Overrides
|
#region Overrides
|
||||||
|
|
||||||
public override IEnumerable<object> Select(ref BuilderContext context) =>
|
public override IEnumerable<object> Select(ref BuilderContext context) =>
|
||||||
base.Select(ref context).Distinct();
|
base.Select(ref context).Distinct();
|
||||||
|
|
||||||
#endregion
|
protected override FieldInfo[] DeclaredMembers(Type type)
|
||||||
|
{
|
||||||
|
return base.DeclaredMembers(type);
|
||||||
#region Implementation
|
}
|
||||||
|
|
||||||
protected override Type MemberType(FieldInfo info)
|
protected override Type MemberType(FieldInfo info)
|
||||||
=> info.FieldType;
|
=> info.FieldType;
|
||||||
|
|
||||||
protected override Expression ResolveExpression(FieldInfo info, string name, object resolver)
|
protected override Expression ResolveExpression(FieldInfo field, string name, object resolver)
|
||||||
=> BuilderContextExpression.Resolve(info, name, resolver);
|
{
|
||||||
|
return Expression.Convert(
|
||||||
|
Expression.Call(BuilderContextExpression.Context, ResolveField,
|
||||||
|
Expression.Constant(field, typeof(FieldInfo)),
|
||||||
|
Expression.Constant(name, typeof(string)),
|
||||||
|
Expression.Constant(resolver, typeof(object))),
|
||||||
|
field.FieldType);
|
||||||
|
}
|
||||||
|
|
||||||
protected override MemberExpression CreateMemberExpression(ParameterExpression variable, FieldInfo info)
|
protected override MemberExpression CreateMemberExpression(FieldInfo info)
|
||||||
=> Expression.Field(variable, info);
|
=> Expression.Field(Expression.Convert(BuilderContextExpression.Existing, info.DeclaringType), info);
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
|
|
|
@ -55,8 +55,9 @@ namespace Unity.Processors
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override Expression CreateExpression(MethodInfo info, object[] resolvers, ParameterExpression variable)
|
protected override Expression CreateExpression(MethodInfo info, object[] resolvers)
|
||||||
=> Expression.Call(variable, info, CreateParameterExpressions(info.GetParameters(), resolvers));
|
=> Expression.Call(Expression.Convert(BuilderContextExpression.Existing, info.DeclaringType),
|
||||||
|
info, CreateParameterExpressions(info.GetParameters(), resolvers));
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,13 +4,27 @@ using System.Linq;
|
||||||
using System.Linq.Expressions;
|
using System.Linq.Expressions;
|
||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
using Unity.Builder;
|
using Unity.Builder;
|
||||||
using Unity.Builder.Expressions;
|
|
||||||
using Unity.Utility;
|
using Unity.Utility;
|
||||||
|
|
||||||
namespace Unity.Processors
|
namespace Unity.Processors
|
||||||
{
|
{
|
||||||
public class PropertiesProcessor : MemberBuildProcessor<PropertyInfo, object>
|
public class PropertiesProcessor : MemberBuildProcessor<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 Overrides
|
#region Overrides
|
||||||
|
|
||||||
public override IEnumerable<object> Select(ref BuilderContext context) =>
|
public override IEnumerable<object> Select(ref BuilderContext context) =>
|
||||||
|
@ -41,21 +55,22 @@ namespace Unity.Processors
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
|
|
||||||
#region Implementation
|
|
||||||
|
|
||||||
protected override Type MemberType(PropertyInfo info)
|
protected override Type MemberType(PropertyInfo info)
|
||||||
=> info.PropertyType;
|
=> info.PropertyType;
|
||||||
|
|
||||||
protected override Expression ResolveExpression(PropertyInfo member, string name, object resolver)
|
protected override Expression ResolveExpression(PropertyInfo property, string name, object resolver)
|
||||||
=> BuilderContextExpression.Resolve(member, name, resolver);
|
{
|
||||||
|
return Expression.Convert(
|
||||||
|
Expression.Call(BuilderContextExpression.Context, ResolveProperty,
|
||||||
|
Expression.Constant(property, typeof(PropertyInfo)),
|
||||||
|
Expression.Constant(name, typeof(string)),
|
||||||
|
Expression.Constant(resolver, typeof(object))),
|
||||||
|
property.PropertyType);
|
||||||
|
}
|
||||||
|
|
||||||
protected override MemberExpression CreateMemberExpression(ParameterExpression variable, PropertyInfo info)
|
protected override MemberExpression CreateMemberExpression(PropertyInfo info)
|
||||||
=> Expression.Property(variable, info);
|
=> Expression.Property(Expression.Convert(BuilderContextExpression.Existing, info.DeclaringType), info);
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,41 +0,0 @@
|
||||||
using System;
|
|
||||||
using Unity.Builder;
|
|
||||||
using Unity.Policy;
|
|
||||||
using Unity.Resolution;
|
|
||||||
|
|
||||||
namespace Unity.ResolverPolicy
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// An implementation of <see cref="IResolve"/> that
|
|
||||||
/// calls back into the build chain to build up the dependency, passing
|
|
||||||
/// a type given at compile time as its build key.
|
|
||||||
/// </summary>
|
|
||||||
public class FixedTypeResolvePolicy : IResolve
|
|
||||||
{
|
|
||||||
private readonly NamedTypeBuildKey _keyToBuild;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Create a new instance storing the given type.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="typeToBuild">Type to resolve.</param>
|
|
||||||
public FixedTypeResolvePolicy(Type typeToBuild)
|
|
||||||
{
|
|
||||||
_keyToBuild = new NamedTypeBuildKey(typeToBuild);
|
|
||||||
}
|
|
||||||
|
|
||||||
#region IResolverPolicy Members
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// GetOrDefault the value for a dependency.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="context">Current build context.</param>
|
|
||||||
/// <returns>The value for the dependency.</returns>
|
|
||||||
public object Resolve<TContext>(ref TContext context)
|
|
||||||
where TContext : IResolveContext
|
|
||||||
{
|
|
||||||
return context.Resolve(_keyToBuild.Type, _keyToBuild.Name);
|
|
||||||
}
|
|
||||||
|
|
||||||
#endregion
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,35 +0,0 @@
|
||||||
using Unity.Policy;
|
|
||||||
using Unity.Resolution;
|
|
||||||
|
|
||||||
namespace Unity.ResolverPolicy
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// A <see cref="IResolve"/> implementation that returns
|
|
||||||
/// the value set in the constructor.
|
|
||||||
/// </summary>
|
|
||||||
public class LiteralValueDependencyResolvePolicy : IResolve
|
|
||||||
{
|
|
||||||
private readonly object _dependencyValue;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Create a new instance of <see cref="LiteralValueDependencyResolvePolicy"/>
|
|
||||||
/// which will return the given value when resolved.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="dependencyValue">The value to return.</param>
|
|
||||||
public LiteralValueDependencyResolvePolicy(object dependencyValue)
|
|
||||||
{
|
|
||||||
_dependencyValue = dependencyValue;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// GetOrDefault the value for a dependency.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="context">Current build context.</param>
|
|
||||||
/// <returns>The value for the dependency.</returns>
|
|
||||||
public object Resolve<TContext>(ref TContext context)
|
|
||||||
where TContext : IResolveContext
|
|
||||||
{
|
|
||||||
return _dependencyValue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,47 +0,0 @@
|
||||||
using System;
|
|
||||||
using Unity.Policy;
|
|
||||||
using Unity.Resolution;
|
|
||||||
|
|
||||||
namespace Unity.ResolverPolicy
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// An implementation of <see cref="IResolve"/> that stores a
|
|
||||||
/// type and name, and at resolution time puts them together into a
|
|
||||||
/// <see cref="NamedTypeBuildKey"/>.
|
|
||||||
/// </summary>
|
|
||||||
public class NamedTypeDependencyResolvePolicy : IResolve
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// Create an instance of <see cref="NamedTypeDependencyResolvePolicy"/>
|
|
||||||
/// with the given type and name.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="type">The type.</param>
|
|
||||||
/// <param name="name">The name (may be null).</param>
|
|
||||||
public NamedTypeDependencyResolvePolicy(Type type, string name)
|
|
||||||
{
|
|
||||||
Type = type;
|
|
||||||
Name = name;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Resolve the value for a dependency.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="context">Current build context.</param>
|
|
||||||
/// <returns>The value for the dependency.</returns>
|
|
||||||
public object Resolve<TContext>(ref TContext context)
|
|
||||||
where TContext : IResolveContext
|
|
||||||
{
|
|
||||||
return context.Resolve(Type, Name);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// The type that this resolver resolves.
|
|
||||||
/// </summary>
|
|
||||||
public Type Type { get; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// The name that this resolver resolves.
|
|
||||||
/// </summary>
|
|
||||||
public string Name { get; }
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,77 +0,0 @@
|
||||||
using System;
|
|
||||||
using System.Globalization;
|
|
||||||
using System.Reflection;
|
|
||||||
using Unity.Policy;
|
|
||||||
using Unity.Resolution;
|
|
||||||
|
|
||||||
namespace Unity.ResolverPolicy
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// A <see cref="IResolve"/> that will attempt to
|
|
||||||
/// resolve a value, and return null if it cannot rather than throwing.
|
|
||||||
/// </summary>
|
|
||||||
public class OptionalDependencyResolvePolicy : IResolve
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// Construct a new <see cref="OptionalDependencyResolvePolicy"/> object
|
|
||||||
/// that will attempt to resolve the given name and type from the container.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="type">Type to resolve. Must be a reference type.</param>
|
|
||||||
/// <param name="name">Name to resolve with.</param>
|
|
||||||
public OptionalDependencyResolvePolicy(Type type, string name)
|
|
||||||
{
|
|
||||||
if ((type ?? throw new ArgumentNullException(nameof(type))).GetTypeInfo().IsValueType)
|
|
||||||
{
|
|
||||||
throw new ArgumentException(
|
|
||||||
string.Format(CultureInfo.CurrentCulture,
|
|
||||||
Constants.OptionalDependenciesMustBeReferenceTypes,
|
|
||||||
type.GetTypeInfo().Name));
|
|
||||||
}
|
|
||||||
|
|
||||||
DependencyType = type;
|
|
||||||
Name = name;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Construct a new <see cref="OptionalDependencyResolvePolicy"/> object
|
|
||||||
/// that will attempt to resolve the given type from the container.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="type">Type to resolve. Must be a reference type.</param>
|
|
||||||
public OptionalDependencyResolvePolicy(Type type)
|
|
||||||
: this(type, null)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Type this resolver will resolve.
|
|
||||||
/// </summary>
|
|
||||||
public Type DependencyType { get; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Name this resolver will resolve.
|
|
||||||
/// </summary>
|
|
||||||
public string Name { get; }
|
|
||||||
|
|
||||||
#region IResolverPolicy Members
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// GetOrDefault the value for a dependency.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="context">Current build context.</param>
|
|
||||||
/// <returns>The value for the dependency.</returns>
|
|
||||||
public object Resolve<TContext>(ref TContext context)
|
|
||||||
where TContext : IResolveContext
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
return context.Resolve(DependencyType, Name);
|
|
||||||
}
|
|
||||||
catch (Exception)
|
|
||||||
{
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#endregion
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -167,7 +167,7 @@ namespace Unity
|
||||||
? containerRegistration.Type : type,
|
? containerRegistration.Type : type,
|
||||||
};
|
};
|
||||||
|
|
||||||
return registration.BuildChain.ExecuteThrowingPlan(ref context);
|
return ExecutePlan(registration.BuildChain, ref context);
|
||||||
}
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
@ -197,7 +197,7 @@ namespace Unity
|
||||||
? containerRegistration.Type : type
|
? containerRegistration.Type : type
|
||||||
};
|
};
|
||||||
|
|
||||||
return registration.BuildChain.ExecuteThrowingPlan(ref context);
|
return ExecutePlan(registration.BuildChain, ref context);
|
||||||
}
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
|
@ -340,6 +340,34 @@ namespace Unity
|
||||||
return argType;
|
return argType;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static object ExecutePlan(BuilderStrategy[] chain, ref BuilderContext context)
|
||||||
|
{
|
||||||
|
var i = -1;
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
while (!context.BuildComplete && ++i < chain.Length)
|
||||||
|
{
|
||||||
|
chain[i].PreBuildUp(ref context);
|
||||||
|
}
|
||||||
|
|
||||||
|
while (--i >= 0)
|
||||||
|
{
|
||||||
|
chain[i].PostBuildUp(ref context);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
context.RequiresRecovery?.Recover();
|
||||||
|
// TODO: 5.9.0 Add proper error message
|
||||||
|
throw new ResolutionFailedException(context.RegistrationType,
|
||||||
|
context.RegistrationName,
|
||||||
|
"", ex);
|
||||||
|
}
|
||||||
|
|
||||||
|
return context.Existing;
|
||||||
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -5,7 +5,6 @@ using System.Linq.Expressions;
|
||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using Unity.Builder;
|
using Unity.Builder;
|
||||||
using Unity.Builder.Expressions;
|
|
||||||
using Unity.Exceptions;
|
using Unity.Exceptions;
|
||||||
using Unity.Policy;
|
using Unity.Policy;
|
||||||
using Unity.Registration;
|
using Unity.Registration;
|
||||||
|
@ -164,8 +163,6 @@ namespace Unity
|
||||||
|
|
||||||
private ResolveDelegate<BuilderContext> GetResolver(ref BuilderContext context)
|
private ResolveDelegate<BuilderContext> GetResolver(ref BuilderContext context)
|
||||||
{
|
{
|
||||||
context.Variable = Expression.Variable(context.Type, "instance");
|
|
||||||
|
|
||||||
var expressions = new List<Expression>();
|
var expressions = new List<Expression>();
|
||||||
|
|
||||||
foreach (var processor in _processorsChain)
|
foreach (var processor in _processorsChain)
|
||||||
|
@ -174,11 +171,10 @@ namespace Unity
|
||||||
expressions.Add(step);
|
expressions.Add(step);
|
||||||
}
|
}
|
||||||
|
|
||||||
expressions.Add(Expression.Convert(context.Variable, typeof(object)));
|
expressions.Add(BuilderContextExpression.Existing);
|
||||||
|
|
||||||
var lambda = Expression.Lambda<ResolveDelegate<BuilderContext>>(
|
var lambda = Expression.Lambda<ResolveDelegate<BuilderContext>>(
|
||||||
Expression.Block(new ParameterExpression[] { context.Variable }, expressions),
|
Expression.Block(expressions), BuilderContextExpression.Context);
|
||||||
BuilderContextExpression.Context);
|
|
||||||
|
|
||||||
return lambda.Compile();
|
return lambda.Compile();
|
||||||
}
|
}
|
||||||
|
@ -194,7 +190,7 @@ namespace Unity
|
||||||
var builder = new StringBuilder();
|
var builder = new StringBuilder();
|
||||||
|
|
||||||
builder.AppendLine($"Resolution of the dependency failed for type = '{typeRequested}', name = '{FormatName(nameRequested)}'.");
|
builder.AppendLine($"Resolution of the dependency failed for type = '{typeRequested}', name = '{FormatName(nameRequested)}'.");
|
||||||
builder.AppendLine($"Exception occurred while: {ExceptionReason(ref context)}.");
|
builder.AppendLine($"Exception occurred while: {Constants.NoOperationExceptionReason}.");
|
||||||
builder.AppendLine($"Exception is: {innerException?.GetType().GetTypeInfo().Name ?? "ResolutionFailedException"} - {innerException?.Message}");
|
builder.AppendLine($"Exception is: {innerException?.GetType().GetTypeInfo().Name ?? "ResolutionFailedException"} - {innerException?.Message}");
|
||||||
builder.AppendLine("-----------------------------------------------");
|
builder.AppendLine("-----------------------------------------------");
|
||||||
builder.AppendLine("At the time of the exception, the container was: ");
|
builder.AppendLine("At the time of the exception, the container was: ");
|
||||||
|
@ -227,33 +223,6 @@ namespace Unity
|
||||||
return string.IsNullOrEmpty(name) ? "(none)" : name;
|
return string.IsNullOrEmpty(name) ? "(none)" : name;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static string ExceptionReason(ref BuilderContext context)
|
|
||||||
{
|
|
||||||
//var deepestContext = context;
|
|
||||||
|
|
||||||
//// Find deepest child
|
|
||||||
//while (deepestContext.ChildContext != null)
|
|
||||||
//{
|
|
||||||
// deepestContext = deepestContext.ChildContext;
|
|
||||||
//}
|
|
||||||
|
|
||||||
// Backtrack to last known operation
|
|
||||||
|
|
||||||
return Constants.NoOperationExceptionReason;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static string OperationError(object operation)
|
|
||||||
{
|
|
||||||
switch (operation)
|
|
||||||
{
|
|
||||||
case ConstructorInfo ctor:
|
|
||||||
return $"Calling constructor {ctor}";
|
|
||||||
|
|
||||||
default:
|
|
||||||
return operation.ToString();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,25 +20,28 @@ namespace Runner.Tests
|
||||||
_container.RegisterType<Poco>();
|
_container.RegisterType<Poco>();
|
||||||
_container.RegisterType<IService, Service>();
|
_container.RegisterType<IService, Service>();
|
||||||
_container.RegisterType<IService, Service>("1");
|
_container.RegisterType<IService, Service>("1");
|
||||||
_container.RegisterType<IService, Service>("2");
|
_container.RegisterType<IService>("2", Invoke.Factory(c => new Service()));
|
||||||
}
|
}
|
||||||
|
|
||||||
[Benchmark(Description = "Resolve<IUnityContainer>")]
|
[Benchmark(Description = "Resolve<IUnityContainer> ")]
|
||||||
public object IUnityContainer() => _container.Resolve(typeof(IUnityContainer), null);
|
public object IUnityContainer() => _container.Resolve(typeof(IUnityContainer), null);
|
||||||
|
|
||||||
[Benchmark(Description = "Resolve<object> (unregistered)")]
|
[Benchmark(Description = "Resolve<object> (unregistered)")]
|
||||||
public object Unregistered() => _container.Resolve(typeof(object), null);
|
public object Unregistered() => _container.Resolve(typeof(object), null);
|
||||||
|
|
||||||
[Benchmark(Description = "Resolve<Poco> (registered)")]
|
[Benchmark(Description = "Resolve<Poco> (registered)")]
|
||||||
public object Transient() => _container.Resolve(typeof(Poco), null);
|
public object Transient() => _container.Resolve(typeof(Poco), null);
|
||||||
|
|
||||||
[Benchmark(Description = "Resolve<IService> (registered)")]
|
[Benchmark(Description = "Resolve<IService> (registered)")]
|
||||||
public object Mapping() => _container.Resolve(typeof(IService), null);
|
public object Mapping() => _container.Resolve(typeof(IService), null);
|
||||||
|
|
||||||
[Benchmark(Description = "Resolve<IService[]> (registered)")]
|
[Benchmark(Description = "Resolve<IService> (factory)")]
|
||||||
|
public object Factory() => _container.Resolve(typeof(IService), "2");
|
||||||
|
|
||||||
|
[Benchmark(Description = "Resolve<IService[]> (registered)")]
|
||||||
public object Array() => _container.Resolve(typeof(IService[]), null);
|
public object Array() => _container.Resolve(typeof(IService[]), null);
|
||||||
|
|
||||||
[Benchmark(Description = "Resolve<IEnumerable<IService>> (registered)")]
|
[Benchmark(Description = "Resolve<IEnumerable<IService>> (registered)")]
|
||||||
public object Enumerable() => _container.Resolve(typeof(IEnumerable<IService>), null);
|
public object Enumerable() => _container.Resolve(typeof(IEnumerable<IService>), null);
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -20,7 +20,7 @@ namespace Runner.Tests
|
||||||
_container.RegisterType<Poco>();
|
_container.RegisterType<Poco>();
|
||||||
_container.RegisterType<IService, Service>();
|
_container.RegisterType<IService, Service>();
|
||||||
_container.RegisterType<IService, Service>("1");
|
_container.RegisterType<IService, Service>("1");
|
||||||
_container.RegisterType<IService, Service>("2");
|
_container.RegisterType<IService>("2", Invoke.Factory(c => new Service()));
|
||||||
|
|
||||||
_container.Resolve<object>();
|
_container.Resolve<object>();
|
||||||
_container.Resolve<Poco>();
|
_container.Resolve<Poco>();
|
||||||
|
@ -41,6 +41,9 @@ namespace Runner.Tests
|
||||||
[Benchmark(Description = "Resolve<IService> (pre-built)")]
|
[Benchmark(Description = "Resolve<IService> (pre-built)")]
|
||||||
public object Mapping() => _container.Resolve(typeof(IService), null);
|
public object Mapping() => _container.Resolve(typeof(IService), null);
|
||||||
|
|
||||||
|
[Benchmark(Description = "Resolve<IService> (factory)")]
|
||||||
|
public object Factory() => _container.Resolve(typeof(IService), "2");
|
||||||
|
|
||||||
[Benchmark(Description = "Resolve<IService[]> (pre-built)")]
|
[Benchmark(Description = "Resolve<IService[]> (pre-built)")]
|
||||||
public object Array() => _container.Resolve(typeof(IService[]), null);
|
public object Array() => _container.Resolve(typeof(IService[]), null);
|
||||||
|
|
||||||
|
|
|
@ -3,8 +3,6 @@ using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using Unity.Injection;
|
using Unity.Injection;
|
||||||
using Unity.Policy;
|
|
||||||
using Unity.ResolverPolicy;
|
|
||||||
using Unity.Tests.v5.Generics;
|
using Unity.Tests.v5.Generics;
|
||||||
using Unity.Tests.v5.TestSupport;
|
using Unity.Tests.v5.TestSupport;
|
||||||
|
|
||||||
|
|
|
@ -5,7 +5,6 @@ using Unity.Builder;
|
||||||
using Unity.Extension;
|
using Unity.Extension;
|
||||||
using Unity.Injection;
|
using Unity.Injection;
|
||||||
using Unity.Policy;
|
using Unity.Policy;
|
||||||
using Unity.ResolverPolicy;
|
|
||||||
using Unity.Strategies;
|
using Unity.Strategies;
|
||||||
using Unity.Tests.v5.TestSupport;
|
using Unity.Tests.v5.TestSupport;
|
||||||
|
|
||||||
|
|
Загрузка…
Ссылка в новой задаче