Moved to delegate factory for resolver
This commit is contained in:
Родитель
cf55bd92ea
Коммит
d10edf57cc
|
@ -1,5 +1,6 @@
|
|||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.Linq.Expressions;
|
||||
using System.Reflection;
|
||||
using System.Security;
|
||||
using Unity.Policy;
|
||||
|
@ -24,8 +25,58 @@ namespace Unity.Builder
|
|||
#endregion
|
||||
|
||||
|
||||
#region IResolveContext
|
||||
|
||||
public IUnityContainer Container => Lifetime?.Container;
|
||||
|
||||
public Type Type { get; set; }
|
||||
|
||||
public string Name => RegistrationName;
|
||||
|
||||
public object Resolve(Type type, string name) => Resolve(type, name,
|
||||
(InternalRegistration)((UnityContainer)Container).GetRegistration(type, name));
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
#region IPolicyList
|
||||
|
||||
public object Get(Type type, string name, Type policyInterface)
|
||||
{
|
||||
return list.Get(type, name, policyInterface) ??
|
||||
(type != RegistrationType || name != RegistrationName
|
||||
? ((UnityContainer)Container).GetPolicy(type, name, policyInterface)
|
||||
: Registration.Get(policyInterface));
|
||||
}
|
||||
|
||||
public void Set(Type type, string name, Type policyInterface, object policy)
|
||||
{
|
||||
list.Set(type, name, policyInterface, policy);
|
||||
}
|
||||
|
||||
public void Clear(Type type, string name, Type policyInterface)
|
||||
{
|
||||
list.Clear(type, name, policyInterface);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
#region Registration
|
||||
|
||||
public Type RegistrationType { get; set; }
|
||||
|
||||
public string RegistrationName { get; set; }
|
||||
|
||||
public IPolicySet Registration { get; set; }
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
#region Public Members
|
||||
|
||||
public object Existing { get; set; }
|
||||
|
||||
public ILifetimeContainer Lifetime;
|
||||
|
||||
public SynchronizedLifetimeManager RequiresRecovery;
|
||||
|
@ -34,17 +85,12 @@ namespace Unity.Builder
|
|||
|
||||
public Type DeclaringType { get; private set; }
|
||||
|
||||
public ParameterExpression Variable;
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
#region ResolveContext
|
||||
|
||||
public IUnityContainer Container => Lifetime?.Container;
|
||||
|
||||
public object Existing { get; set; }
|
||||
|
||||
public object Resolve(Type type, string name) => Resolve(type, name,
|
||||
(InternalRegistration)((UnityContainer)Container).GetRegistration(type, name));
|
||||
#region Public Methods
|
||||
|
||||
public object Resolve(Type type, string name, InternalRegistration registration)
|
||||
{
|
||||
|
@ -64,6 +110,63 @@ namespace Unity.Builder
|
|||
return registration.BuildChain.ExecuteReThrowingPlan(ref context);
|
||||
}
|
||||
|
||||
public object Resolve(ParameterInfo parameter, string name, object value)
|
||||
{
|
||||
var context = this;
|
||||
|
||||
// Process overrides if any
|
||||
if (null != Overrides)
|
||||
{
|
||||
// Check if this parameter is overridden
|
||||
for (var index = Overrides.Length - 1; index >= 0; --index)
|
||||
{
|
||||
var resolverOverride = Overrides[index];
|
||||
|
||||
// If matches with current parameter
|
||||
if (resolverOverride is IEquatable<ParameterInfo> comparer && comparer.Equals(parameter))
|
||||
{
|
||||
// Check if itself is a value
|
||||
if (resolverOverride is IResolve resolverPolicy)
|
||||
{
|
||||
return resolverPolicy.Resolve(ref context);
|
||||
}
|
||||
|
||||
// Try to create value
|
||||
var resolveDelegate = resolverOverride.GetResolver<BuilderContext>(parameter.ParameterType);
|
||||
if (null != resolveDelegate)
|
||||
{
|
||||
return resolveDelegate(ref context);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Resolve from injectors
|
||||
// TODO: Optimize via overrides
|
||||
switch (value)
|
||||
{
|
||||
case ResolveDelegate<BuilderContext> resolver:
|
||||
return resolver(ref context);
|
||||
|
||||
case IResolve policy:
|
||||
return policy.Resolve(ref context);
|
||||
|
||||
case IResolverFactory factory:
|
||||
var method = factory.GetResolver<BuilderContext>(Type);
|
||||
return method?.Invoke(ref context);
|
||||
|
||||
case Type type: // TODO: Requires evaluation
|
||||
if (typeof(Type) == parameter.ParameterType) return type;
|
||||
break;
|
||||
|
||||
case object obj:
|
||||
return obj;
|
||||
}
|
||||
|
||||
// Resolve from container
|
||||
return Resolve(parameter.ParameterType, name);
|
||||
}
|
||||
|
||||
public object Resolve(FieldInfo field, string name, object value)
|
||||
{
|
||||
var context = this;
|
||||
|
@ -174,101 +277,6 @@ namespace Unity.Builder
|
|||
return Resolve(property.PropertyType, name);
|
||||
}
|
||||
|
||||
public object Resolve(ParameterInfo parameter, string name, object value)
|
||||
{
|
||||
var context = this;
|
||||
|
||||
// Process overrides if any
|
||||
if (null != Overrides)
|
||||
{
|
||||
// Check if this parameter is overridden
|
||||
for (var index = Overrides.Length - 1; index >= 0; --index)
|
||||
{
|
||||
var resolverOverride = Overrides[index];
|
||||
|
||||
// If matches with current parameter
|
||||
if (resolverOverride is IEquatable<ParameterInfo> comparer && comparer.Equals(parameter))
|
||||
{
|
||||
// Check if itself is a value
|
||||
if (resolverOverride is IResolve resolverPolicy)
|
||||
{
|
||||
return resolverPolicy.Resolve(ref context);
|
||||
}
|
||||
|
||||
// Try to create value
|
||||
var resolveDelegate = resolverOverride.GetResolver<BuilderContext>(parameter.ParameterType);
|
||||
if (null != resolveDelegate)
|
||||
{
|
||||
return resolveDelegate(ref context);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Resolve from injectors
|
||||
// TODO: Optimize via overrides
|
||||
switch (value)
|
||||
{
|
||||
case ResolveDelegate<BuilderContext> resolver:
|
||||
return resolver(ref context);
|
||||
|
||||
case IResolve policy:
|
||||
return policy.Resolve(ref context);
|
||||
|
||||
case IResolverFactory factory:
|
||||
var method = factory.GetResolver<BuilderContext>(Type);
|
||||
return method?.Invoke(ref context);
|
||||
|
||||
case Type type: // TODO: Requires evaluation
|
||||
if (typeof(Type) == parameter.ParameterType) return type;
|
||||
break;
|
||||
|
||||
case object obj:
|
||||
return obj;
|
||||
}
|
||||
|
||||
// Resolve from container
|
||||
return Resolve(parameter.ParameterType, name);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
#region Registration
|
||||
|
||||
public Type RegistrationType { get; set; }
|
||||
|
||||
public string RegistrationName { get; set; }
|
||||
|
||||
public IPolicySet Registration { get; set; }
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
#region Build
|
||||
|
||||
public Type Type { get; set; }
|
||||
|
||||
public string Name => RegistrationName;
|
||||
|
||||
public object Get(Type type, string name, Type policyInterface)
|
||||
{
|
||||
return list.Get(type, name, policyInterface) ??
|
||||
(type != RegistrationType || name != RegistrationName
|
||||
? ((UnityContainer)Container).GetPolicy(type, name, policyInterface)
|
||||
: Registration.Get(policyInterface));
|
||||
}
|
||||
|
||||
public void Set(Type type, string name, Type policyInterface, object policy)
|
||||
{
|
||||
list.Set(type, name, policyInterface, policy);
|
||||
}
|
||||
|
||||
public void Clear(Type type, string name, Type policyInterface)
|
||||
{
|
||||
list.Clear(type, name, policyInterface);
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,8 +1,10 @@
|
|||
using System.Collections.Generic;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using System;
|
||||
using System.Linq;
|
||||
using System.Linq.Expressions;
|
||||
using System.Reflection;
|
||||
using Unity.Container.Lifetime;
|
||||
using Unity.Resolution;
|
||||
using Unity.ResolverPolicy;
|
||||
|
||||
|
@ -11,6 +13,45 @@ namespace Unity.Builder.Expressions
|
|||
[SuppressMessage("ReSharper", "StaticMemberInGenericType")]
|
||||
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()
|
||||
|
@ -33,6 +74,36 @@ namespace Unity.Builder.Expressions
|
|||
|
||||
#region Methods
|
||||
|
||||
public static Expression Resolve(FieldInfo field, string name, object value = null)
|
||||
{
|
||||
return Expression.Convert(
|
||||
Expression.Call(Context, _resolveField,
|
||||
Expression.Constant(field, typeof(FieldInfo)),
|
||||
Expression.Constant(name, typeof(string)),
|
||||
Expression.Constant(value, typeof(object))),
|
||||
field.FieldType);
|
||||
}
|
||||
|
||||
public static Expression Resolve(PropertyInfo property, string name, object value = null)
|
||||
{
|
||||
return Expression.Convert(
|
||||
Expression.Call(Context, _resolveProperty,
|
||||
Expression.Constant(property, typeof(PropertyInfo)),
|
||||
Expression.Constant(name, typeof(string)),
|
||||
Expression.Constant(value, typeof(object))),
|
||||
property.PropertyType);
|
||||
}
|
||||
|
||||
public static Expression Resolve(ParameterInfo parameter, string name, object value = null)
|
||||
{
|
||||
return Expression.Convert(
|
||||
Expression.Call(Context, _resolveParameter,
|
||||
Expression.Constant(parameter, typeof(ParameterInfo)),
|
||||
Expression.Constant(name, typeof(string)),
|
||||
Expression.Constant(value, typeof(object))),
|
||||
parameter.ParameterType);
|
||||
}
|
||||
|
||||
public static IEnumerable<Expression> GetParameters(MethodBase methodBase)
|
||||
{
|
||||
foreach (var parameter in methodBase.GetParameters())
|
||||
|
@ -68,6 +139,12 @@ namespace Unity.Builder.Expressions
|
|||
}
|
||||
}
|
||||
|
||||
public static Expression SetPerBuildSingleton(ref BuilderContext context)
|
||||
{
|
||||
return Set(context.RegistrationType, context.RegistrationName, typeof(LifetimeManager),
|
||||
Expression.New(_perResolveInfo, context.Variable));
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,37 +0,0 @@
|
|||
using System;
|
||||
using Unity.Builder;
|
||||
using Unity.Policy;
|
||||
using Unity.Resolution;
|
||||
|
||||
namespace Unity.ObjectBuilder.BuildPlan.DynamicMethod
|
||||
{
|
||||
public class DynamicMethodBuildPlan : IBuildPlanPolicy, IResolve
|
||||
{
|
||||
private readonly Delegate _buildMethod;
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="buildMethod"></param>
|
||||
public DynamicMethodBuildPlan(Delegate buildMethod)
|
||||
{
|
||||
_buildMethod = buildMethod;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="context"></param>
|
||||
public void BuildUp(ref BuilderContext context)
|
||||
{
|
||||
context.Existing = ((ResolveDelegate<BuilderContext>)_buildMethod).Invoke(ref context);
|
||||
|
||||
}
|
||||
|
||||
public object Resolve<TContext>(ref TContext context)
|
||||
where TContext : IResolveContext
|
||||
{
|
||||
return ((ResolveDelegate<TContext>)_buildMethod).Invoke(ref context);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,55 +0,0 @@
|
|||
using System;
|
||||
using Unity.Builder;
|
||||
using Unity.Policy;
|
||||
using Unity.Storage;
|
||||
|
||||
namespace Unity.ObjectBuilder.BuildPlan.DynamicMethod
|
||||
{
|
||||
/// <summary>
|
||||
/// An <see cref="IBuildPlanCreatorPolicy"/> implementation
|
||||
/// that constructs a build plan via dynamic IL emission.
|
||||
/// </summary>
|
||||
public class DynamicMethodBuildPlanCreatorPolicy : IBuildPlanCreatorPolicy
|
||||
{
|
||||
private BuilderStrategy[] _strategies;
|
||||
|
||||
/// <summary>
|
||||
/// Construct a <see cref="DynamicMethodBuildPlanCreatorPolicy"/> that
|
||||
/// uses the given strategy chain to construct the build plan.
|
||||
/// </summary>
|
||||
/// <param name="strategies">The strategy chain.</param>
|
||||
public DynamicMethodBuildPlanCreatorPolicy(StagedStrategyChain<BuilderStrategy, BuilderStage> strategies)
|
||||
{
|
||||
strategies.Invalidated += (s, e) => _strategies = strategies.ToArray();
|
||||
_strategies = strategies.ToArray();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Construct a build plan.
|
||||
/// </summary>
|
||||
/// <param name="context">The current build context.</param>
|
||||
/// <param name="type"></param>
|
||||
/// <param name="name"></param>
|
||||
/// <returns>The created build plan.</returns>
|
||||
public IBuildPlanPolicy CreatePlan(ref BuilderContext context, Type type, string name)
|
||||
{
|
||||
var generatorContext = new DynamicBuildPlanGenerationContext(type);
|
||||
|
||||
var planContext = new BuilderContext
|
||||
{
|
||||
Existing = generatorContext,
|
||||
Lifetime = context.Lifetime,
|
||||
RegistrationType = context.RegistrationType,
|
||||
RegistrationName = context.RegistrationName,
|
||||
Registration = context.Registration,
|
||||
Type = context.Type,
|
||||
|
||||
list = context.list
|
||||
};
|
||||
|
||||
var plan = _strategies.ExecutePlan(ref planContext);
|
||||
|
||||
return new DynamicMethodBuildPlan(generatorContext.GetBuildMethod());
|
||||
}
|
||||
}
|
||||
}
|
|
@ -3,10 +3,7 @@ using Unity.Builder;
|
|||
|
||||
namespace Unity.Policy
|
||||
{
|
||||
/// <summary>
|
||||
/// A policy that can create and return an <see cref="IBuildPlanPolicy"/>
|
||||
/// for the given build key.
|
||||
/// </summary>
|
||||
[Obsolete("This interface has been replaced with Unity.Policy.ResolveDelegateFactory delegate", true)]
|
||||
public interface IBuildPlanCreatorPolicy
|
||||
{
|
||||
/// <summary>
|
|
@ -2,15 +2,14 @@
|
|||
using System.Reflection;
|
||||
using Unity.Builder;
|
||||
using Unity.Container.Lifetime;
|
||||
using Unity.ObjectBuilder.BuildPlan.DynamicMethod;
|
||||
|
||||
namespace Unity.Policy.BuildPlanCreator
|
||||
{
|
||||
/// <summary>
|
||||
/// An <see cref="IBuildPlanCreatorPolicy"/> implementation
|
||||
/// An <see cref="IResolveDelegateFactory"/> implementation
|
||||
/// that constructs a build plan for creating <see cref="Lazy{T}"/> objects.
|
||||
/// </summary>
|
||||
public class GenericLazyBuildPlanCreatorPolicy : IBuildPlanCreatorPolicy
|
||||
public class GenericLazyBuildPlanCreatorPolicy
|
||||
{
|
||||
#region Fields
|
||||
|
||||
|
@ -21,14 +20,14 @@ namespace Unity.Policy.BuildPlanCreator
|
|||
#endregion
|
||||
|
||||
|
||||
#region IBuildPlanCreatorPolicy
|
||||
#region IResolveDelegateFactory
|
||||
|
||||
public IBuildPlanPolicy CreatePlan(ref BuilderContext context, Type type, string name)
|
||||
public static ResolveDelegate<BuilderContext> GetResolver(ref BuilderContext context)
|
||||
{
|
||||
var itemType = context.Type.GetTypeInfo().GenericTypeArguments[0];
|
||||
var lazyMethod = BuildResolveLazyMethod.MakeGenericMethod(itemType);
|
||||
|
||||
return new DynamicMethodBuildPlan(lazyMethod.CreateDelegate(typeof(ResolveDelegate<BuilderContext>)));
|
||||
return (ResolveDelegate<BuilderContext>)lazyMethod.CreateDelegate(typeof(ResolveDelegate<BuilderContext>));
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
|
|
@ -0,0 +1,11 @@
|
|||
using Unity.Builder;
|
||||
|
||||
namespace Unity.Policy
|
||||
{
|
||||
public delegate ResolveDelegate<BuilderContext> ResolveDelegateFactory(ref BuilderContext context);
|
||||
|
||||
public interface IResolveDelegateFactory
|
||||
{
|
||||
ResolveDelegate<BuilderContext> GetResolver(ref BuilderContext context);
|
||||
}
|
||||
}
|
|
@ -42,28 +42,39 @@ namespace Unity.Strategies
|
|||
var resolver = context.Registration.Get<ResolveDelegate<BuilderContext>>();
|
||||
if (null == resolver)
|
||||
{
|
||||
|
||||
// Legacy support
|
||||
// TODO: Verify and optimize getting default
|
||||
var plan = context.Registration.Get<IBuildPlanPolicy>() ??
|
||||
var plan = context.Registration.Get<IBuildPlanPolicy>() ??
|
||||
(IBuildPlanPolicy)(
|
||||
context.Get(context.Type, string.Empty, typeof(IBuildPlanPolicy)) ??
|
||||
GetGeneric(ref context, typeof(IBuildPlanPolicy),
|
||||
context.RegistrationType, context.RegistrationName));
|
||||
GetGeneric(ref context, typeof(IBuildPlanPolicy), context.RegistrationType, context.RegistrationName));
|
||||
|
||||
if (plan == null || plan is OverriddenBuildPlanMarkerPolicy)
|
||||
if (plan == null)
|
||||
{
|
||||
var planCreator = context.Registration.Get<IBuildPlanCreatorPolicy>() ??
|
||||
CheckIfOpenGeneric(context.RegistrationType, context.Registration) ??
|
||||
Get_Policy<IBuildPlanCreatorPolicy>(ref context, context.Type, context.Name);
|
||||
|
||||
if (planCreator != null)
|
||||
// Check if can create
|
||||
#if NETCOREAPP1_0 || NETSTANDARD1_0
|
||||
if (!(context.Registration is ContainerRegistration) && context.RegistrationType.GetTypeInfo().IsGenericTypeDefinition)
|
||||
#else
|
||||
if (!(context.Registration is ContainerRegistration) && context.RegistrationType.IsGenericTypeDefinition)
|
||||
#endif
|
||||
{
|
||||
plan = planCreator.CreatePlan(ref context, context.Type, context.Name);
|
||||
throw new ArgumentException(string.Format(CultureInfo.CurrentCulture,
|
||||
Constants.CannotResolveOpenGenericType, context.RegistrationType.FullName));
|
||||
}
|
||||
|
||||
if (plan is IResolve policy)
|
||||
context.Registration.Set(typeof(ResolveDelegate<BuilderContext>), (ResolveDelegate<BuilderContext>)policy.Resolve);
|
||||
else
|
||||
context.Registration.Set(typeof(IBuildPlanPolicy), plan);
|
||||
// Create plan
|
||||
var factory = context.Registration.Get<ResolveDelegateFactory>() ??
|
||||
Get_Policy<ResolveDelegateFactory>(ref context, context.Type, context.Name);
|
||||
|
||||
if (null != factory)
|
||||
{
|
||||
resolver = factory(ref context);
|
||||
|
||||
context.Registration.Set(typeof(ResolveDelegate<BuilderContext>), resolver);
|
||||
context.Existing = resolver(ref context);
|
||||
|
||||
return;
|
||||
}
|
||||
else
|
||||
throw new ResolutionFailedException(context.Type, context.Name, "Failed to find Build Plan Creator Policy");
|
||||
|
@ -105,22 +116,6 @@ namespace Unity.Strategies
|
|||
return null;
|
||||
}
|
||||
|
||||
protected static IBuildPlanCreatorPolicy CheckIfOpenGeneric(Type type, IPolicySet namedType)
|
||||
{
|
||||
if (namedType is InternalRegistration registration && !(namedType is ContainerRegistration) &&
|
||||
#if NETCOREAPP1_0 || NETSTANDARD1_0
|
||||
type.GetTypeInfo().IsGenericTypeDefinition)
|
||||
#else
|
||||
type.IsGenericTypeDefinition)
|
||||
#endif
|
||||
{
|
||||
throw new ArgumentException(string.Format(CultureInfo.CurrentCulture,
|
||||
Constants.CannotResolveOpenGenericType, type.FullName));
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
|
|
|
@ -10,7 +10,6 @@ using Unity.Builder.Strategies;
|
|||
using Unity.Container.Lifetime;
|
||||
using Unity.Events;
|
||||
using Unity.Extension;
|
||||
using Unity.ObjectBuilder.BuildPlan.DynamicMethod;
|
||||
using Unity.Policy;
|
||||
using Unity.Policy.BuildPlanCreator;
|
||||
using Unity.Registration;
|
||||
|
@ -133,7 +132,7 @@ namespace Unity
|
|||
Set(null, null, GetDefaultPolicies());
|
||||
Set(typeof(Func<>), string.Empty, typeof(LifetimeManager), new PerResolveLifetimeManager());
|
||||
Set(typeof(Func<>), string.Empty, typeof(IBuildPlanPolicy), new DeferredResolveCreatorPolicy());
|
||||
Set(typeof(Lazy<>), string.Empty, typeof(IBuildPlanCreatorPolicy), new GenericLazyBuildPlanCreatorPolicy());
|
||||
Set(typeof(Lazy<>), string.Empty, typeof(ResolveDelegateFactory), (ResolveDelegateFactory)GenericLazyBuildPlanCreatorPolicy.GetResolver);
|
||||
|
||||
// Register this instance
|
||||
((IUnityContainer)this).RegisterInstance(typeof(IUnityContainer), null, this, new ContainerLifetimeManager());
|
||||
|
@ -187,7 +186,7 @@ namespace Unity
|
|||
{
|
||||
var defaults = new InternalRegistration(null, null);
|
||||
|
||||
defaults.Set(typeof(IBuildPlanCreatorPolicy), new DynamicMethodBuildPlanCreatorPolicy(_buildPlanStrategies));
|
||||
defaults.Set(typeof(ResolveDelegateFactory), (ResolveDelegateFactory)GetResolver);
|
||||
defaults.Set(typeof(IConstructorSelectorPolicy), new DefaultUnityConstructorSelector());
|
||||
defaults.Set(typeof(IFieldSelectorPolicy), new DefaultUnityFieldsSelector());
|
||||
defaults.Set(typeof(IPropertySelectorPolicy), new DefaultUnityPropertiesSelector());
|
||||
|
|
|
@ -5,6 +5,7 @@ using System.Reflection;
|
|||
using System.Text;
|
||||
using Unity.Builder;
|
||||
using Unity.Exceptions;
|
||||
using Unity.Policy;
|
||||
using Unity.Registration;
|
||||
using Unity.Storage;
|
||||
|
||||
|
@ -157,6 +158,55 @@ namespace Unity
|
|||
#endregion
|
||||
|
||||
|
||||
#region Build Plan
|
||||
|
||||
|
||||
private ResolveDelegate<BuilderContext> GetResolver(ref BuilderContext context)
|
||||
{
|
||||
var generatorContext = new ObjectBuilder.BuildPlan.DynamicMethod.DynamicBuildPlanGenerationContext(context.Type);
|
||||
|
||||
var planContext = new BuilderContext
|
||||
{
|
||||
Existing = generatorContext,
|
||||
Lifetime = context.Lifetime,
|
||||
RegistrationType = context.RegistrationType,
|
||||
RegistrationName = context.RegistrationName,
|
||||
Registration = context.Registration,
|
||||
Type = context.Type,
|
||||
|
||||
list = context.list
|
||||
};
|
||||
|
||||
var plan = _buildPlanStrategies.ToArray().ExecutePlan(ref planContext);
|
||||
|
||||
return generatorContext.GetBuildMethod();
|
||||
}
|
||||
|
||||
|
||||
//private ResolveDelegate<BuilderContext> GetResolver(ref BuilderContext context)
|
||||
//{
|
||||
// context.Variable = Expression.Variable(context.Type, "instance");
|
||||
|
||||
// var expressions = new List<Expression>();
|
||||
|
||||
// foreach (var strategy in _buildPlanStrategies.ToArray())
|
||||
// {
|
||||
// //foreach (var step in strategy.BuildUp(ref context))
|
||||
// // expressions.Add(step);
|
||||
// }
|
||||
|
||||
// expressions.Add(Expression.Convert(context.Variable, typeof(object)));
|
||||
|
||||
// var lambda = Expression.Lambda<ResolveDelegate<BuilderContext>>(
|
||||
// Expression.Block(new ParameterExpression[] { context.Variable }, expressions),
|
||||
// BuilderContextExpression.Context);
|
||||
|
||||
// return lambda.Compile();
|
||||
//}
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
#region Exceptions
|
||||
|
||||
public static string CreateMessage(Type typeRequested, string nameRequested, Exception innerException,
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
using BenchmarkDotNet.Configs;
|
||||
using BenchmarkDotNet.Jobs;
|
||||
using BenchmarkDotNet.Validators;
|
||||
using System.Linq;
|
||||
|
||||
namespace Runner.Setup
|
||||
{
|
||||
|
@ -9,11 +8,12 @@ namespace Runner.Setup
|
|||
{
|
||||
public BenchmarkConfiguration()
|
||||
{
|
||||
Add(JitOptimizationsValidator.DontFailOnError); // ALLOW NON-OPTIMIZED DLLS
|
||||
|
||||
Add(Job.Default
|
||||
.WithUnrollFactor(1)
|
||||
.WithInvocationCount(50000));
|
||||
.WithInvocationCount(1));
|
||||
|
||||
Add(JitOptimizationsValidator.DontFailOnError); // ALLOW NON-OPTIMIZED DLLS
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -22,6 +22,7 @@ namespace Runner.Tests
|
|||
_container.RegisterType<IService, Service>("1");
|
||||
_container.RegisterType<IService, Service>("2");
|
||||
|
||||
_container.Resolve<object>();
|
||||
_container.Resolve<Poco>();
|
||||
_container.Resolve<IService>();
|
||||
_container.Resolve<IService>("1");
|
||||
|
|
|
@ -1,162 +0,0 @@
|
|||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Linq.Expressions;
|
||||
using System.Reflection;
|
||||
using Unity.Builder;
|
||||
using Unity.Policy;
|
||||
using Unity.Resolution;
|
||||
using Unity.ResolverPolicy;
|
||||
|
||||
namespace Unity.Tests.v5
|
||||
{
|
||||
[TestClass]
|
||||
public class ExpressionFixture
|
||||
{
|
||||
public IUnityContainer _container;
|
||||
public MockContext _context = new MockContext();
|
||||
|
||||
[TestInitialize]
|
||||
public void Setup()
|
||||
{
|
||||
_container = new UnityContainer();
|
||||
_context.Existing = null;
|
||||
_context.Type = typeof(Service);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void CreateNewExpression()
|
||||
{
|
||||
ref var context = ref _context;
|
||||
|
||||
var fieldInfo = context.Type.GetField(nameof(Service.Field));
|
||||
var propInfo = context.Type.GetProperty(nameof(Service.Property));
|
||||
|
||||
var varExpr = Expression.Variable(context.Type, "instance");
|
||||
|
||||
var fieldExpr = Expression.Field(varExpr, fieldInfo);
|
||||
var propExpr = Expression.Property(varExpr, propInfo);
|
||||
|
||||
var blockExpr = Expression.Block(new ParameterExpression[] { varExpr }, new Expression[]
|
||||
{
|
||||
Expression.IfThenElse(Expression.NotEqual( Expression.Constant(null), BuilderContextExpression.Existing),
|
||||
Expression.Assign( varExpr, Expression.Convert(BuilderContextExpression.Existing, context.Type)),
|
||||
Expression.Assign( varExpr, Expression.New(typeof(Service)))),
|
||||
|
||||
Expression.Assign(fieldExpr, BuilderContextExpression.Resolve(fieldInfo, null, null)),
|
||||
Expression.Assign(propExpr, BuilderContextExpression.Resolve(propInfo, null, null)),
|
||||
|
||||
varExpr
|
||||
});
|
||||
|
||||
|
||||
var lambda = Expression.Lambda<ResolveDelegate<MockContext>>(blockExpr, BuilderContextExpression.Context);
|
||||
var plan = lambda.Compile();
|
||||
var instance = (Service)plan(ref context);
|
||||
|
||||
Assert.IsNotNull(instance);
|
||||
Assert.AreEqual(instance.Field, Service.First);
|
||||
Assert.AreEqual(instance.Property, Service.Other);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void BaselineTest()
|
||||
{
|
||||
ResolveDelegate<BuilderContext> plan = (ref BuilderContext context) =>
|
||||
{
|
||||
Service instance;
|
||||
if (null == context.Existing)
|
||||
{
|
||||
instance = new Service();
|
||||
}
|
||||
else
|
||||
{
|
||||
instance = (Service)context.Existing;
|
||||
}
|
||||
|
||||
instance.Field = Service.First;
|
||||
instance.Property = Service.Other;
|
||||
|
||||
return instance;
|
||||
};
|
||||
|
||||
var result = new Service();
|
||||
result.Field = Service.First;
|
||||
result.Property = Service.Other;
|
||||
|
||||
Assert.IsNotNull(result);
|
||||
Assert.AreEqual(result.Field, Service.First);
|
||||
Assert.AreEqual(result.Property, Service.Other);
|
||||
}
|
||||
|
||||
|
||||
public interface IService { }
|
||||
public class Service : IService
|
||||
{
|
||||
public static string First = "name";
|
||||
public static string Other = "other";
|
||||
|
||||
public string Field;
|
||||
|
||||
public string Property { get; set; }
|
||||
}
|
||||
|
||||
public class BuilderContextExpression : IResolveContextExpression<MockContext>
|
||||
{
|
||||
public static readonly MemberExpression Existing =
|
||||
Expression.MakeMemberAccess(Context, typeof(MockContext).GetTypeInfo()
|
||||
.GetDeclaredProperty(nameof(MockContext.Existing)));
|
||||
}
|
||||
|
||||
public struct MockContext : IResolveContext
|
||||
{
|
||||
|
||||
#region ResolveContext
|
||||
|
||||
public IUnityContainer Container => null;
|
||||
|
||||
public object Existing { get; set; }
|
||||
|
||||
public object Resolve(Type type, string name)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public object Resolve(FieldInfo field, string name, object value) => Service.First;
|
||||
|
||||
public object Resolve(PropertyInfo property, string name, object value) => Service.Other;
|
||||
|
||||
public object Resolve(ParameterInfo parameter, string name, object value)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
#region Build
|
||||
|
||||
public Type Type { get; set; }
|
||||
|
||||
public string Name { get; set; }
|
||||
|
||||
public object Get(Type type, string name, Type policyInterface)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public void Set(Type type, string name, Type policyInterface, object policy)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public void Clear(Type type, string name, Type policyInterface)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
}
|
Загрузка…
Ссылка в новой задаче