From d10edf57cca0862c88cf095c0aa23b6b50d3467f Mon Sep 17 00:00:00 2001 From: Eugene Sadovoi Date: Mon, 24 Dec 2018 21:53:21 -0500 Subject: [PATCH] Moved to delegate factory for resolver --- src/Builder/Context/BuilderContext.cs | 214 +++++++++--------- .../Expressions/BuilderContextExpression.cs | 77 +++++++ .../DynamicMethod/DynamicMethodBuildPlan.cs | 37 --- .../DynamicMethodBuildPlanCreatorPolicy.cs | 55 ----- .../IBuildPlanCreatorPolicy.cs | 5 +- .../GenericLazyBuildPlanCreatorPolicy.cs | 11 +- src/Policy/IResolveDelegateFactory.cs | 11 + src/Strategies/BuildPlanStrategy.cs | 55 ++--- src/UnityContainer.Implementation.cs | 5 +- src/UnityContainer.Resolution.cs | 50 ++++ .../Configuration/BenchmarkConfiguration.cs | 6 +- tests/Performance/Tests/PreBuilt.cs | 1 + tests/Unity.Tests/ExpressionFixture.cs | 162 ------------- 13 files changed, 286 insertions(+), 403 deletions(-) delete mode 100644 src/Legacy/DynamicMethod/DynamicMethodBuildPlan.cs delete mode 100644 src/Legacy/DynamicMethod/DynamicMethodBuildPlanCreatorPolicy.cs rename src/{Policy => Legacy}/IBuildPlanCreatorPolicy.cs (77%) create mode 100644 src/Policy/IResolveDelegateFactory.cs delete mode 100644 tests/Unity.Tests/ExpressionFixture.cs diff --git a/src/Builder/Context/BuilderContext.cs b/src/Builder/Context/BuilderContext.cs index c958e5bf..f5793292 100644 --- a/src/Builder/Context/BuilderContext.cs +++ b/src/Builder/Context/BuilderContext.cs @@ -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 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(parameter.ParameterType); + if (null != resolveDelegate) + { + return resolveDelegate(ref context); + } + } + } + } + + // Resolve from injectors + // TODO: Optimize via overrides + switch (value) + { + case ResolveDelegate resolver: + return resolver(ref context); + + case IResolve policy: + return policy.Resolve(ref context); + + case IResolverFactory factory: + var method = factory.GetResolver(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 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(parameter.ParameterType); - if (null != resolveDelegate) - { - return resolveDelegate(ref context); - } - } - } - } - - // Resolve from injectors - // TODO: Optimize via overrides - switch (value) - { - case ResolveDelegate resolver: - return resolver(ref context); - - case IResolve policy: - return policy.Resolve(ref context); - - case IResolverFactory factory: - var method = factory.GetResolver(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 } } diff --git a/src/Builder/Expressions/BuilderContextExpression.cs b/src/Builder/Expressions/BuilderContextExpression.cs index 83cad03b..bfa01922 100644 --- a/src/Builder/Expressions/BuilderContextExpression.cs +++ b/src/Builder/Expressions/BuilderContextExpression.cs @@ -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 { + #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 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 } } diff --git a/src/Legacy/DynamicMethod/DynamicMethodBuildPlan.cs b/src/Legacy/DynamicMethod/DynamicMethodBuildPlan.cs deleted file mode 100644 index f283fc09..00000000 --- a/src/Legacy/DynamicMethod/DynamicMethodBuildPlan.cs +++ /dev/null @@ -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; - - /// - /// - /// - /// - public DynamicMethodBuildPlan(Delegate buildMethod) - { - _buildMethod = buildMethod; - } - - /// - /// - /// - /// - public void BuildUp(ref BuilderContext context) - { - context.Existing = ((ResolveDelegate)_buildMethod).Invoke(ref context); - - } - - public object Resolve(ref TContext context) - where TContext : IResolveContext - { - return ((ResolveDelegate)_buildMethod).Invoke(ref context); - } - } -} diff --git a/src/Legacy/DynamicMethod/DynamicMethodBuildPlanCreatorPolicy.cs b/src/Legacy/DynamicMethod/DynamicMethodBuildPlanCreatorPolicy.cs deleted file mode 100644 index 09a0c7be..00000000 --- a/src/Legacy/DynamicMethod/DynamicMethodBuildPlanCreatorPolicy.cs +++ /dev/null @@ -1,55 +0,0 @@ -using System; -using Unity.Builder; -using Unity.Policy; -using Unity.Storage; - -namespace Unity.ObjectBuilder.BuildPlan.DynamicMethod -{ - /// - /// An implementation - /// that constructs a build plan via dynamic IL emission. - /// - public class DynamicMethodBuildPlanCreatorPolicy : IBuildPlanCreatorPolicy - { - private BuilderStrategy[] _strategies; - - /// - /// Construct a that - /// uses the given strategy chain to construct the build plan. - /// - /// The strategy chain. - public DynamicMethodBuildPlanCreatorPolicy(StagedStrategyChain strategies) - { - strategies.Invalidated += (s, e) => _strategies = strategies.ToArray(); - _strategies = strategies.ToArray(); - } - - /// - /// Construct a build plan. - /// - /// The current build context. - /// - /// - /// The created build plan. - 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()); - } - } -} diff --git a/src/Policy/IBuildPlanCreatorPolicy.cs b/src/Legacy/IBuildPlanCreatorPolicy.cs similarity index 77% rename from src/Policy/IBuildPlanCreatorPolicy.cs rename to src/Legacy/IBuildPlanCreatorPolicy.cs index 5840efba..01414bc0 100644 --- a/src/Policy/IBuildPlanCreatorPolicy.cs +++ b/src/Legacy/IBuildPlanCreatorPolicy.cs @@ -3,10 +3,7 @@ using Unity.Builder; namespace Unity.Policy { - /// - /// A policy that can create and return an - /// for the given build key. - /// + [Obsolete("This interface has been replaced with Unity.Policy.ResolveDelegateFactory delegate", true)] public interface IBuildPlanCreatorPolicy { /// diff --git a/src/Policy/BuildPlanCreator/GenericLazyBuildPlanCreatorPolicy.cs b/src/Policy/BuildPlanCreator/GenericLazyBuildPlanCreatorPolicy.cs index e8454434..c35380e6 100644 --- a/src/Policy/BuildPlanCreator/GenericLazyBuildPlanCreatorPolicy.cs +++ b/src/Policy/BuildPlanCreator/GenericLazyBuildPlanCreatorPolicy.cs @@ -2,15 +2,14 @@ using System.Reflection; using Unity.Builder; using Unity.Container.Lifetime; -using Unity.ObjectBuilder.BuildPlan.DynamicMethod; namespace Unity.Policy.BuildPlanCreator { /// - /// An implementation + /// An implementation /// that constructs a build plan for creating objects. /// - 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 GetResolver(ref BuilderContext context) { var itemType = context.Type.GetTypeInfo().GenericTypeArguments[0]; var lazyMethod = BuildResolveLazyMethod.MakeGenericMethod(itemType); - return new DynamicMethodBuildPlan(lazyMethod.CreateDelegate(typeof(ResolveDelegate))); + return (ResolveDelegate)lazyMethod.CreateDelegate(typeof(ResolveDelegate)); } #endregion diff --git a/src/Policy/IResolveDelegateFactory.cs b/src/Policy/IResolveDelegateFactory.cs new file mode 100644 index 00000000..bdd0dc20 --- /dev/null +++ b/src/Policy/IResolveDelegateFactory.cs @@ -0,0 +1,11 @@ +using Unity.Builder; + +namespace Unity.Policy +{ + public delegate ResolveDelegate ResolveDelegateFactory(ref BuilderContext context); + + public interface IResolveDelegateFactory + { + ResolveDelegate GetResolver(ref BuilderContext context); + } +} diff --git a/src/Strategies/BuildPlanStrategy.cs b/src/Strategies/BuildPlanStrategy.cs index 42f503e6..f5c97098 100644 --- a/src/Strategies/BuildPlanStrategy.cs +++ b/src/Strategies/BuildPlanStrategy.cs @@ -42,28 +42,39 @@ namespace Unity.Strategies var resolver = context.Registration.Get>(); if (null == resolver) { + // Legacy support // TODO: Verify and optimize getting default - var plan = context.Registration.Get() ?? + var plan = context.Registration.Get() ?? (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() ?? - CheckIfOpenGeneric(context.RegistrationType, context.Registration) ?? - Get_Policy(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), (ResolveDelegate)policy.Resolve); - else - context.Registration.Set(typeof(IBuildPlanPolicy), plan); + // Create plan + var factory = context.Registration.Get() ?? + Get_Policy(ref context, context.Type, context.Name); + + if (null != factory) + { + resolver = factory(ref context); + + context.Registration.Set(typeof(ResolveDelegate), 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 } } diff --git a/src/UnityContainer.Implementation.cs b/src/UnityContainer.Implementation.cs index 27243a7d..71cac625 100644 --- a/src/UnityContainer.Implementation.cs +++ b/src/UnityContainer.Implementation.cs @@ -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()); diff --git a/src/UnityContainer.Resolution.cs b/src/UnityContainer.Resolution.cs index 19a5de47..22f375bf 100644 --- a/src/UnityContainer.Resolution.cs +++ b/src/UnityContainer.Resolution.cs @@ -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 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 GetResolver(ref BuilderContext context) + //{ + // context.Variable = Expression.Variable(context.Type, "instance"); + + // var expressions = new List(); + + // 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>( + // 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, diff --git a/tests/Performance/Configuration/BenchmarkConfiguration.cs b/tests/Performance/Configuration/BenchmarkConfiguration.cs index 651cdef0..9b78edb1 100644 --- a/tests/Performance/Configuration/BenchmarkConfiguration.cs +++ b/tests/Performance/Configuration/BenchmarkConfiguration.cs @@ -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 } } } diff --git a/tests/Performance/Tests/PreBuilt.cs b/tests/Performance/Tests/PreBuilt.cs index 74ed5b8d..e553d548 100644 --- a/tests/Performance/Tests/PreBuilt.cs +++ b/tests/Performance/Tests/PreBuilt.cs @@ -22,6 +22,7 @@ namespace Runner.Tests _container.RegisterType("1"); _container.RegisterType("2"); + _container.Resolve(); _container.Resolve(); _container.Resolve(); _container.Resolve("1"); diff --git a/tests/Unity.Tests/ExpressionFixture.cs b/tests/Unity.Tests/ExpressionFixture.cs deleted file mode 100644 index 9547eedd..00000000 --- a/tests/Unity.Tests/ExpressionFixture.cs +++ /dev/null @@ -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>(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 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 - { - 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 - } - } -}