This commit is contained in:
Eugene Sadovoi 2018-12-30 16:39:54 -05:00
Родитель 7a48052787
Коммит 7adb340019
19 изменённых файлов: 590 добавлений и 502 удалений

Просмотреть файл

@ -6,18 +6,20 @@ namespace Unity.Extension
{
protected override void Initialize()
{
((UnityContainer)Container).ExecutePlan = UnityContainer.ValidatingExecutePlan;
((UnityContainer)Container).SetDiagnosticPolicies();
Context.ChildContainerCreated += (s, e) => ((UnityContainer)e.ChildContainer).SetDiagnosticPolicies();
}
public void ForceCompile()
{
((UnityContainer)Container)._defaults.Set(typeof(ResolveDelegateFactory),
((UnityContainer)Container).Defaults.Set(typeof(ResolveDelegateFactory),
(ResolveDelegateFactory)((UnityContainer)Container).CompilingFactory);
}
public void DisableCompile()
{
((UnityContainer)Container)._defaults.Set(typeof(ResolveDelegateFactory),
((UnityContainer)Container).Defaults.Set(typeof(ResolveDelegateFactory),
(ResolveDelegateFactory)((UnityContainer)Container).ResolvingFactory);
}
}

Просмотреть файл

@ -11,8 +11,7 @@ namespace Unity.Processors
{
public delegate Expression MemberExpressionFactory(Attribute attribute, Expression member, object info, Type type, object resolver);
public abstract partial class BuildMemberProcessor<TMemberInfo, TData> : BuildMemberProcessor
where TMemberInfo : MemberInfo
public abstract partial class BuildMemberProcessor<TMemberInfo, TData> where TMemberInfo : MemberInfo
{
#region Fields

Просмотреть файл

@ -11,8 +11,7 @@ namespace Unity.Processors
{
public delegate ResolveDelegate<BuilderContext> MemberResolverFactory(Attribute attribute, object info, object resolver, object defaultValue);
public abstract partial class BuildMemberProcessor<TMemberInfo, TData> : BuildMemberProcessor
where TMemberInfo : MemberInfo
public abstract partial class BuildMemberProcessor<TMemberInfo, TData> where TMemberInfo : MemberInfo
{
#region Fields

Просмотреть файл

@ -15,7 +15,7 @@ namespace Unity.Processors
{
#region Fields
private static readonly MethodInfo ResolveParameter =
private readonly MethodInfo ResolveParameter =
typeof(BuilderContext).GetTypeInfo()
.GetDeclaredMethods(nameof(BuilderContext.Resolve))
.First(m =>
@ -101,8 +101,6 @@ namespace Unity.Processors
}
else
{
var variable = Expression.Variable(parameter.ParameterType);
var resolve = ResolveExpression(parameter, null, resolver);
expression = (ref BuilderContext context) =>
{
try
@ -138,7 +136,7 @@ namespace Unity.Processors
}
}
protected override ResolveDelegate<BuilderContext> DependencyResolverFactory(Attribute attribute, object info, object resolver, object defaultValue)
protected override ResolveDelegate<BuilderContext> DependencyResolverFactory(Attribute attribute, object info, object resolver, object defaultValue = null)
{
return (ref BuilderContext context) =>
{
@ -158,7 +156,7 @@ namespace Unity.Processors
};
}
protected override ResolveDelegate<BuilderContext> OptionalDependencyResolverFactory(Attribute attribute, object info, object resolver, object defaultValue)
protected override ResolveDelegate<BuilderContext> OptionalDependencyResolverFactory(Attribute attribute, object info, object resolver, object defaultValue = null)
{
return (ref BuilderContext context) =>
{

Просмотреть файл

@ -0,0 +1,371 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Reflection;
using Unity.Builder;
using Unity.Container.Lifetime;
using Unity.Exceptions;
using Unity.Injection;
using Unity.Policy;
using Unity.Storage;
namespace Unity.Processors
{
public class ConstructorDiagnostic : ConstructorProcessor
{
#region Fields
private static readonly Expression CannotConstructInterfaceExpr =
Expression.IfThen(Expression.Equal(Expression.Constant(null), BuilderContextExpression.Existing),
Expression.Throw(
Expression.New(InvalidOperationExceptionCtor,
Expression.Call(
StringFormat,
Expression.Constant(Constants.CannotConstructInterface),
BuilderContextExpression.Type),
InvalidRegistrationExpression)));
private static readonly Expression CannotConstructAbstractClassExpr =
Expression.IfThen(Expression.Equal(Expression.Constant(null), BuilderContextExpression.Existing),
Expression.Throw(
Expression.New(InvalidOperationExceptionCtor,
Expression.Call(
StringFormat,
Expression.Constant(Constants.CannotConstructAbstractClass),
BuilderContextExpression.Type),
InvalidRegistrationExpression)));
private static readonly Expression CannotConstructDelegateExpr =
Expression.IfThen(Expression.Equal(Expression.Constant(null), BuilderContextExpression.Existing),
Expression.Throw(
Expression.New(InvalidOperationExceptionCtor,
Expression.Call(
StringFormat,
Expression.Constant(Constants.CannotConstructDelegate),
BuilderContextExpression.Type),
InvalidRegistrationExpression)));
private static readonly Expression TypeIsNotConstructableExpr =
Expression.IfThen(Expression.Equal(Expression.Constant(null), BuilderContextExpression.Existing),
Expression.Throw(
Expression.New(InvalidOperationExceptionCtor,
Expression.Call(
StringFormat,
Expression.Constant(Constants.TypeIsNotConstructable),
BuilderContextExpression.Type),
InvalidRegistrationExpression)));
#endregion
#region Constructors
public ConstructorDiagnostic(IPolicySet policySet, Func<Type, bool> isTypeRegistered)
: base(policySet, isTypeRegistered)
{
}
#endregion
#region Expression Overrides
public override IEnumerable<Expression> GetBuildSteps(Type type, IPolicySet registration)
{
// Validate if Type could be created
var exceptionExpr = ValidateConstructedTypeExpression(type);
if (null != exceptionExpr) return new[] { exceptionExpr };
// Select ConstructorInfo
var selector = GetPolicy<ISelect<ConstructorInfo>>(registration);
var selection = selector.Select(type, registration)
.FirstOrDefault();
// Select appropriate ctor for the Type
ConstructorInfo info;
object[] resolvers = null;
switch (selection)
{
case ConstructorInfo memberInfo:
info = memberInfo;
break;
case MethodBaseMember<ConstructorInfo> injectionMember:
(info, resolvers) = injectionMember.FromType(type);
break;
default:
return new[] { NoConstructorExpr };
}
// Get lifetime manager
var lifetimeManager = (LifetimeManager)registration.Get(typeof(LifetimeManager));
// Validate parameters
var parameters = info.GetParameters();
if (parameters.Any(p => p.ParameterType == info.DeclaringType))
{
if (null == lifetimeManager?.GetValue())
{
return new Expression[]
{
Expression.IfThen(Expression.Equal(Expression.Constant(null), BuilderContextExpression.Existing),
Expression.Throw(
Expression.New(InvalidOperationExceptionCtor,
Expression.Call(
StringFormat,
Expression.Constant(Constants.SelectedConstructorHasRefItself),
Expression.Constant(info, typeof(ConstructorInfo)),
BuilderContextExpression.Type),
InvalidRegistrationExpression)))
};
}
}
// Create 'new' expression
var ifThenExpr = Expression.IfThen(
Expression.Equal(Expression.Constant(null), BuilderContextExpression.Existing),
BuildMemberExpression(info, resolvers));
// Check if PerResolveLifetimeManager is required
return lifetimeManager is PerResolveLifetimeManager
? new[] { ifThenExpr, SetPerBuildSingletonExpr }
: new Expression[] { ifThenExpr };
}
protected override Expression BuildMemberExpression(ConstructorInfo info, object[] resolvers)
{
// Check if had ByRef parameters
var parameters = info.GetParameters();
if (parameters.Any(pi => pi.ParameterType.IsByRef))
{
return Expression.Throw(Expression.New(InvalidOperationExceptionCtor,
Expression.Constant(CreateErrorMessage(Constants.SelectedConstructorHasRefParameters, info.DeclaringType, info)),
InvalidRegistrationExpression));
}
// Create
var variable = Expression.Variable(info.DeclaringType ?? throw new ArgumentNullException(nameof(info)));
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)))
});
// TODO: Check if required
string CreateErrorMessage(string format, Type type, MethodBase constructor)
{
var parameterDescriptions =
constructor.GetParameters()
.Select(parameter => $"{parameter.ParameterType.FullName} {parameter.Name}");
return string.Format(format, type.FullName, string.Join(", ", parameterDescriptions));
}
}
#endregion
#region Overrides
public override ResolveDelegate<BuilderContext> GetResolver(Type type, IPolicySet registration, ResolveDelegate<BuilderContext> seed)
{
// Validate if Type could be created
var exception = ValidateConstructedTypeResolver(type);
if (null != exception) return exception;
// Select ConstructorInfo
var selector = GetPolicy<ISelect<ConstructorInfo>>(registration);
var selection = selector.Select(type, registration)
.FirstOrDefault();
// Select appropriate ctor for the Type
ConstructorInfo info;
object[] resolvers = null;
switch (selection)
{
case ConstructorInfo memberInfo:
info = memberInfo;
break;
case MethodBaseMember<ConstructorInfo> injectionMember:
(info, resolvers) = injectionMember.FromType(type);
break;
default:
return (ref BuilderContext c) =>
{
if (null == c.Existing)
throw new InvalidOperationException($"No public constructor is available for type {c.Type}.",
new InvalidRegistrationException());
return c.Existing;
};
}
// Get lifetime manager
var lifetimeManager = (LifetimeManager)registration.Get(typeof(LifetimeManager));
// Validate parameters
var parameters = info.GetParameters();
if (parameters.Any(p => p.ParameterType == info.DeclaringType))
{
if (null == lifetimeManager?.GetValue())
return (ref BuilderContext c) =>
{
if (null == c.Existing)
throw new InvalidOperationException(string.Format(Constants.SelectedConstructorHasRefItself, info, c.Type),
new InvalidRegistrationException());
return c.Existing;
};
}
// Create dependency resolvers
var parameterResolvers = CreateParameterResolvers(parameters, resolvers).ToArray();
if (lifetimeManager is PerResolveLifetimeManager)
{
// PerResolve lifetime
return (ref BuilderContext c) =>
{
if (null == c.Existing)
{
var dependencies = new object[parameterResolvers.Length];
for (var i = 0; i < dependencies.Length; i++)
dependencies[i] = parameterResolvers[i](ref c);
c.Existing = info.Invoke(dependencies);
c.Set(typeof(LifetimeManager),
new InternalPerResolveLifetimeManager(c.Existing));
}
return c.Existing;
};
}
// Normal activator
return (ref BuilderContext c) =>
{
if (null == c.Existing)
{
var dependencies = new object[parameterResolvers.Length];
for (var i = 0; i < dependencies.Length; i++)
dependencies[i] = parameterResolvers[i](ref c);
c.Existing = info.Invoke(dependencies);
}
return c.Existing;
};
}
#endregion
#region Implementation
private ResolveDelegate<BuilderContext> ValidateConstructedTypeResolver(Type type)
{
#if NETSTANDARD1_0 || NETCOREAPP1_0
var typeInfo = type.GetTypeInfo();
if (typeInfo.IsInterface)
#else
if (type.IsInterface)
#endif
{
return (ref BuilderContext c) =>
{
if (null == c.Existing)
throw new InvalidOperationException(string.Format(Constants.CannotConstructInterface, c.Type),
new InvalidRegistrationException());
return c.Existing;
};
}
#if NETSTANDARD1_0 || NETCOREAPP1_0
if (typeInfo.IsAbstract)
#else
if (type.IsAbstract)
#endif
{
return (ref BuilderContext c) =>
{
if (null == c.Existing)
throw new InvalidOperationException(string.Format(Constants.CannotConstructAbstractClass, c.Type),
new InvalidRegistrationException());
return c.Existing;
};
}
#if NETSTANDARD1_0 || NETCOREAPP1_0
if (typeInfo.IsSubclassOf(typeof(Delegate)))
#else
if (type.IsSubclassOf(typeof(Delegate)))
#endif
{
return (ref BuilderContext c) =>
{
if (null == c.Existing)
throw new InvalidOperationException(string.Format(Constants.CannotConstructDelegate, c.Type),
new InvalidRegistrationException());
return c.Existing;
};
}
if (type == typeof(string))
{
return (ref BuilderContext c) =>
{
if (null == c.Existing)
throw new InvalidOperationException(string.Format(Constants.TypeIsNotConstructable, c.Type),
new InvalidRegistrationException());
return c.Existing;
};
}
return null;
}
private Expression ValidateConstructedTypeExpression(Type type)
{
#if NETSTANDARD1_0 || NETCOREAPP1_0
var typeInfo = type.GetTypeInfo();
if (typeInfo.IsInterface)
#else
if (type.IsInterface)
#endif
return CannotConstructInterfaceExpr;
#if NETSTANDARD1_0 || NETCOREAPP1_0
if (typeInfo.IsAbstract)
#else
if (type.IsAbstract)
#endif
return CannotConstructAbstractClassExpr;
#if NETSTANDARD1_0 || NETCOREAPP1_0
if (typeInfo.IsSubclassOf(typeof(Delegate)))
#else
if (type.IsSubclassOf(typeof(Delegate)))
#endif
return CannotConstructDelegateExpr;
if (type == typeof(string))
return TypeIsNotConstructableExpr;
return null;
}
#endregion
}
}

Просмотреть файл

@ -15,15 +15,7 @@ namespace Unity.Processors
{
#region Fields
private static readonly MethodInfo SetMethod =
typeof(BuilderContext).GetTypeInfo()
.GetDeclaredMethods(nameof(BuilderContext.Set))
.First(m => 2 == m.GetParameters().Length);
private static readonly ConstructorInfo PerResolveInfo = typeof(InternalPerResolveLifetimeManager)
.GetTypeInfo().DeclaredConstructors.First();
private static readonly ConstructorInfo InvalidOperationExceptionCtor =
protected static readonly ConstructorInfo InvalidOperationExceptionCtor =
typeof(InvalidOperationException)
.GetTypeInfo()
.DeclaredConstructors
@ -35,57 +27,25 @@ namespace Unity.Processors
typeof(Exception) == parameters[1].ParameterType;
});
private static readonly Expression NoConstructorExpr =
Expression.IfThen(Expression.Equal(Expression.Constant(null), BuilderContextExpression.Existing),
Expression.Throw(
Expression.New(InvalidOperationExceptionCtor,
Expression.Call(StringFormat,
Expression.Constant("No public constructor is available for type {0}."),
BuilderContextExpression.Type),
InvalidRegistrationExpression)));
private static readonly MethodInfo SetMethod =
typeof(BuilderContext).GetTypeInfo()
.GetDeclaredMethods(nameof(BuilderContext.Set))
.First(m => 2 == m.GetParameters().Length);
private static readonly Expression SetPerBuildSingletonExpr =
private static readonly ConstructorInfo PerResolveInfo = typeof(InternalPerResolveLifetimeManager)
.GetTypeInfo().DeclaredConstructors.First();
protected static readonly Expression SetPerBuildSingletonExpr =
Expression.Call(BuilderContextExpression.Context, SetMethod,
Expression.Constant(typeof(LifetimeManager), typeof(Type)),
Expression.New(PerResolveInfo, BuilderContextExpression.Existing));
private static readonly Expression CannotConstructInterfaceExpr =
protected static readonly Expression NoConstructorExpr =
Expression.IfThen(Expression.Equal(Expression.Constant(null), BuilderContextExpression.Existing),
Expression.Throw(
Expression.Throw(
Expression.New(InvalidOperationExceptionCtor,
Expression.Call(
StringFormat,
Expression.Constant(Constants.CannotConstructInterface),
BuilderContextExpression.Type),
InvalidRegistrationExpression)));
private static readonly Expression CannotConstructAbstractClassExpr =
Expression.IfThen(Expression.Equal(Expression.Constant(null), BuilderContextExpression.Existing),
Expression.Throw(
Expression.New(InvalidOperationExceptionCtor,
Expression.Call(
StringFormat,
Expression.Constant(Constants.CannotConstructAbstractClass),
BuilderContextExpression.Type),
InvalidRegistrationExpression)));
private static readonly Expression CannotConstructDelegateExpr =
Expression.IfThen(Expression.Equal(Expression.Constant(null), BuilderContextExpression.Existing),
Expression.Throw(
Expression.New(InvalidOperationExceptionCtor,
Expression.Call(
StringFormat,
Expression.Constant(Constants.CannotConstructDelegate),
BuilderContextExpression.Type),
InvalidRegistrationExpression)));
private static readonly Expression TypeIsNotConstructableExpr =
Expression.IfThen(Expression.Equal(Expression.Constant(null), BuilderContextExpression.Existing),
Expression.Throw(
Expression.New(InvalidOperationExceptionCtor,
Expression.Call(
StringFormat,
Expression.Constant(Constants.TypeIsNotConstructable),
Expression.Call(StringFormat,
Expression.Constant("No public constructor is available for type {0}."),
BuilderContextExpression.Type),
InvalidRegistrationExpression)));
@ -96,19 +56,11 @@ namespace Unity.Processors
public override IEnumerable<Expression> GetBuildSteps(Type type, IPolicySet registration)
{
// Validate if Type could be created
var exceptionExpr = ValidateConstructedTypeExpression(type);
if (null != exceptionExpr) return new[] { exceptionExpr };
// Select ConstructorInfo
var selector = GetPolicy<ISelect<ConstructorInfo>>(registration);
var selection = selector.Select(type, registration)
.FirstOrDefault();
// Validate constructor info
if (null == selection) return new[] { NoConstructorExpr };
// Select appropriate ctor for the Type
ConstructorInfo info;
object[] resolvers = null;
@ -124,111 +76,28 @@ namespace Unity.Processors
break;
default:
throw new InvalidOperationException($"Unknown constructor representation");
return new[] { NoConstructorExpr };
}
// Get lifetime manager
var lifetimeManager = (LifetimeManager)registration.Get(typeof(LifetimeManager));
// Validate parameters
var parameters = info.GetParameters();
if (parameters.Any(p => p.ParameterType == info.DeclaringType))
{
if (null == lifetimeManager?.GetValue())
{
return new Expression[]
{
Expression.IfThen(Expression.Equal(Expression.Constant(null), BuilderContextExpression.Existing),
Expression.Throw(
Expression.New(InvalidOperationExceptionCtor,
Expression.Call(
StringFormat,
Expression.Constant(Constants.SelectedConstructorHasRefItself),
Expression.Constant(info, typeof(ConstructorInfo)),
BuilderContextExpression.Type),
InvalidRegistrationExpression)))
};
}
}
// Create 'new' expression
var variable = Expression.Variable(info.DeclaringType);
var ifThenExpr = Expression.IfThen(
Expression.Equal(Expression.Constant(null), BuilderContextExpression.Existing),
BuildMemberExpression(info, resolvers));
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)))
}));
// Check if PerResolveLifetimeManager is required
return registration.Get(typeof(LifetimeManager)) is PerResolveLifetimeManager
return lifetimeManager is PerResolveLifetimeManager
? new[] { ifThenExpr, SetPerBuildSingletonExpr }
: new Expression[] { ifThenExpr };
}
protected override Expression BuildMemberExpression(ConstructorInfo info, object[] resolvers)
{
// Check if had ByRef parameters
var parameters = info.GetParameters();
if (parameters.Any(pi => pi.ParameterType.IsByRef))
{
return Expression.Throw(Expression.New(InvalidOperationExceptionCtor,
Expression.Constant(CreateErrorMessage(Constants.SelectedConstructorHasRefParameters, info.DeclaringType, info)),
InvalidRegistrationExpression));
}
// Create
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)))
});
// TODO: Check if required
string CreateErrorMessage(string format, Type type, MethodBase constructor)
{
var parameterDescriptions =
constructor.GetParameters()
.Select(parameter => $"{parameter.ParameterType.FullName} {parameter.Name}");
return string.Format(format, type.FullName, string.Join(", ", parameterDescriptions));
}
}
#endregion
#region Implementation
private Expression ValidateConstructedTypeExpression(Type type)
{
#if NETSTANDARD1_0 || NETCOREAPP1_0
var typeInfo = type.GetTypeInfo();
if (typeInfo.IsInterface)
#else
if (type.IsInterface)
#endif
return CannotConstructInterfaceExpr;
#if NETSTANDARD1_0 || NETCOREAPP1_0
if (typeInfo.IsAbstract)
#else
if (type.IsAbstract)
#endif
return CannotConstructAbstractClassExpr;
#if NETSTANDARD1_0 || NETCOREAPP1_0
if (typeInfo.IsSubclassOf(typeof(Delegate)))
#else
if (type.IsSubclassOf(typeof(Delegate)))
#endif
return CannotConstructDelegateExpr;
if (type == typeof(string))
return TypeIsNotConstructableExpr;
return null;
}
#endregion
}
}

Просмотреть файл

@ -16,27 +16,10 @@ namespace Unity.Processors
public override ResolveDelegate<BuilderContext> GetResolver(Type type, IPolicySet registration, ResolveDelegate<BuilderContext> seed)
{
// Validate if Type could be created
var exception = ValidateConstructedTypeResolver(type);
if (null != exception) return exception;
// Select ConstructorInfo
var selector = GetPolicy<ISelect<ConstructorInfo>>(registration);
var selection = selector.Select(type, registration)
.FirstOrDefault();
// Validate constructor info
if (null == selection)
{
return (ref BuilderContext c) =>
{
if (null == c.Existing)
throw new InvalidOperationException($"No public constructor is available for type {c.Type}.",
new InvalidRegistrationException());
return c.Existing;
};
}
// Select appropriate ctor for the Type
ConstructorInfo info;
@ -53,29 +36,21 @@ namespace Unity.Processors
break;
default:
throw new InvalidOperationException($"Unknown constructor representation");
}
// Get lifetime manager
var lifetimeManager = (LifetimeManager)registration.Get(typeof(LifetimeManager));
// Validate parameters
var parameters = info.GetParameters();
if (parameters.Any(p => p.ParameterType == info.DeclaringType))
{
if (null == lifetimeManager?.GetValue())
return (ref BuilderContext c) =>
{
if (null == c.Existing)
throw new InvalidOperationException(string.Format(Constants.SelectedConstructorHasRefItself, info, c.Type),
throw new InvalidOperationException($"No public constructor is available for type {c.Type}.",
new InvalidRegistrationException());
return c.Existing;
};
}
// Get lifetime manager
var lifetimeManager = (LifetimeManager)registration.Get(typeof(LifetimeManager));
// Create dependency resolvers
var parameterResolvers = CreateParameterResolvers(parameters, resolvers).ToArray();
var parameterResolvers = CreateParameterResolvers(info.GetParameters(), resolvers).ToArray();
if (lifetimeManager is PerResolveLifetimeManager)
{
// PerResolve lifetime
@ -114,76 +89,5 @@ namespace Unity.Processors
}
#endregion
#region Implementation
private ResolveDelegate<BuilderContext> ValidateConstructedTypeResolver(Type type)
{
#if NETSTANDARD1_0 || NETCOREAPP1_0
var typeInfo = type.GetTypeInfo();
if (typeInfo.IsInterface)
#else
if (type.IsInterface)
#endif
{
return (ref BuilderContext c) =>
{
if (null == c.Existing)
throw new InvalidOperationException(string.Format(Constants.CannotConstructInterface, c.Type),
new InvalidRegistrationException());
return c.Existing;
};
}
#if NETSTANDARD1_0 || NETCOREAPP1_0
if (typeInfo.IsAbstract)
#else
if (type.IsAbstract)
#endif
{
return (ref BuilderContext c) =>
{
if (null == c.Existing)
throw new InvalidOperationException(string.Format(Constants.CannotConstructAbstractClass, c.Type),
new InvalidRegistrationException());
return c.Existing;
};
}
#if NETSTANDARD1_0 || NETCOREAPP1_0
if (typeInfo.IsSubclassOf(typeof(Delegate)))
#else
if (type.IsSubclassOf(typeof(Delegate)))
#endif
{
return (ref BuilderContext c) =>
{
if (null == c.Existing)
throw new InvalidOperationException(string.Format(Constants.CannotConstructDelegate, c.Type),
new InvalidRegistrationException());
return c.Existing;
};
}
if (type == typeof(string))
{
return (ref BuilderContext c) =>
{
if (null == c.Existing)
throw new InvalidOperationException(string.Format(Constants.TypeIsNotConstructable, c.Type),
new InvalidRegistrationException());
return c.Existing;
};
}
return null;
}
#endregion
}
}

Просмотреть файл

@ -1,42 +0,0 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using Unity.Registration;
namespace Unity
{
[DebuggerDisplay("{DebugName()}")]
[DebuggerTypeProxy(typeof(UnityContainerDebugProxy))]
public partial class UnityContainer
{
private string DebugName()
{
var types = (_registrations?.Keys ?? Enumerable.Empty<Type>())
.SelectMany(t => _registrations[t].Values)
.OfType<ContainerRegistration>()
.Count();
if (null == _parent) return $"Container[{types}]";
return _parent.DebugName() + $".Child[{types}]"; ;
}
internal class UnityContainerDebugProxy
{
private readonly IUnityContainer _container;
public UnityContainerDebugProxy(IUnityContainer container)
{
_container = container;
ID = container.GetHashCode().ToString();
}
public string ID { get; }
public IEnumerable<IContainerRegistration> Registrations => _container.Registrations;
}
}
}

Просмотреть файл

@ -0,0 +1,84 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Reflection;
using Unity.Builder;
using Unity.Policy;
using Unity.Processors;
using Unity.Registration;
using Unity.Storage;
namespace Unity
{
[DebuggerDisplay("{DebugName()}")]
[DebuggerTypeProxy(typeof(UnityContainerDebugProxy))]
public partial class UnityContainer
{
#region Diagnostic Registrations
internal void SetDiagnosticPolicies()
{
// Default policies
Defaults = new InternalRegistration(typeof(ResolveDelegate<BuilderContext>),
(ResolveDelegate<BuilderContext>)ExecuteDefaultPlan);
// Processors
var fieldsProcessor = new FieldsProcessor(Defaults);
var methodsProcessor = new MethodsProcessor(Defaults);
var propertiesProcessor = new PropertiesProcessor(Defaults);
var constructorProcessor = new ConstructorDiagnostic(Defaults, IsTypeExplicitlyRegistered);
// Processors chain
_processors = new StagedStrategyChain<BuildMemberProcessor, BuilderStage>
{
{ constructorProcessor, BuilderStage.Creation },
{ fieldsProcessor, BuilderStage.Fields },
{ propertiesProcessor, BuilderStage.Properties },
{ methodsProcessor, BuilderStage.Methods }
};
// Caches
_processors.Invalidated += (s, e) => _processorsChain = _processors.ToArray();
_processorsChain = _processors.ToArray();
Defaults.Set(typeof(ResolveDelegateFactory), (ResolveDelegateFactory)OptimizingFactory);
Defaults.Set(typeof(ISelect<ConstructorInfo>), constructorProcessor);
Defaults.Set(typeof(ISelect<FieldInfo>), fieldsProcessor);
Defaults.Set(typeof(ISelect<PropertyInfo>), propertiesProcessor);
Defaults.Set(typeof(ISelect<MethodInfo>), methodsProcessor);
ExecutePlan = UnityContainer.ValidatingExecutePlan;
}
#endregion
private string DebugName()
{
var types = (_registrations?.Keys ?? Enumerable.Empty<Type>())
.SelectMany(t => _registrations[t].Values)
.OfType<ContainerRegistration>()
.Count();
if (null == _parent) return $"Container[{types}]";
return _parent.DebugName() + $".Child[{types}]";
}
internal class UnityContainerDebugProxy
{
private readonly IUnityContainer _container;
public UnityContainerDebugProxy(IUnityContainer container)
{
_container = container;
ID = container.GetHashCode().ToString();
}
public string ID { get; }
public IEnumerable<IContainerRegistration> Registrations => _container.Registrations;
}
}
}

Просмотреть файл

@ -136,7 +136,7 @@ namespace Unity
/// <inheritdoc />
bool IUnityContainer.IsRegistered(Type type, string name) =>
ReferenceEquals(string.Empty, name) ? _isTypeExplicitlyRegistered(type)
ReferenceEquals(string.Empty, name) ? IsTypeExplicitlyRegistered(type)
: _isExplicitlyRegistered(type, name);
/// <inheritdoc />

Просмотреть файл

@ -73,7 +73,7 @@ namespace Unity
[DebuggerBrowsable(DebuggerBrowsableState.Never)] private Func<Type, string, IPolicySet> _get;
[DebuggerBrowsable(DebuggerBrowsableState.Never)] private Func<Type, string, bool> _isExplicitlyRegistered;
[DebuggerBrowsable(DebuggerBrowsableState.Never)] private Func<Type, string, Type, IPolicySet> _getGenericRegistration;
[DebuggerBrowsable(DebuggerBrowsableState.Never)] private Func<Type, bool> _isTypeExplicitlyRegistered;
[DebuggerBrowsable(DebuggerBrowsableState.Never)] internal Func<Type, bool> IsTypeExplicitlyRegistered;
#endregion
@ -100,7 +100,7 @@ namespace Unity
_get = Get;
_getGenericRegistration = GetOrAddGeneric;
_isExplicitlyRegistered = IsExplicitlyRegisteredLocally;
_isTypeExplicitlyRegistered = IsTypeTypeExplicitlyRegisteredLocally;
IsTypeExplicitlyRegistered = IsTypeTypeExplicitlyRegisteredLocally;
GetRegistration = GetOrAdd;
Register = AddOrUpdate;
@ -134,8 +134,8 @@ namespace Unity
// Default Policies and Strategies
_defaults = InitializeDefaultPolicies();
Set(null, null, _defaults);
SetDefaultPolicies();
Set(null, null, Defaults);
Set(typeof(Func<>), string.Empty, typeof(LifetimeManager), new PerResolveLifetimeManager());
Set(typeof(Func<>), string.Empty, typeof(ResolveDelegateFactory), (ResolveDelegateFactory)DeferredFuncResolverFactory.DeferredResolveDelegateFactory);
Set(typeof(Lazy<>), string.Empty, typeof(ResolveDelegateFactory), (ResolveDelegateFactory)GenericLazyResolverFactory.GetResolver);
@ -166,7 +166,7 @@ namespace Unity
_get = _parent._get;
_getGenericRegistration = _parent._getGenericRegistration;
_isExplicitlyRegistered = _parent._isExplicitlyRegistered;
_isTypeExplicitlyRegistered = _parent._isTypeExplicitlyRegistered;
IsTypeExplicitlyRegistered = _parent.IsTypeExplicitlyRegistered;
GetRegistration = _parent.GetRegistration;
Register = CreateAndSetOrUpdate;
@ -180,7 +180,7 @@ namespace Unity
_strategies.Invalidated += OnStrategiesChanged;
// Caches
_defaults = InitializeDefaultPolicies();
SetDefaultPolicies();
}
#endregion
@ -212,20 +212,27 @@ namespace Unity
private void SetupChildContainerBehaviors()
{
_registrations = new HashRegistry<Type, IRegistry<string, IPolicySet>>(ContainerInitialCapacity);
Set(null, null, _defaults);
lock (_syncRoot)
{
if (null == _registrations)
{
_registrations = new HashRegistry<Type, IRegistry<string, IPolicySet>>(ContainerInitialCapacity);
Set(null, null, Defaults);
Register = AddOrUpdate;
GetPolicy = Get;
SetPolicy = Set;
ClearPolicy = Clear;
Register = AddOrUpdate;
GetPolicy = Get;
SetPolicy = Set;
ClearPolicy = Clear;
GetRegistration = GetDynamicRegistration;
GetRegistration = GetDynamicRegistration;
_get = (type, name) => Get(type, name) ?? _parent._get(type, name);
_getGenericRegistration = GetOrAddGeneric;
IsTypeExplicitlyRegistered = IsTypeTypeExplicitlyRegisteredLocally;
_isExplicitlyRegistered = IsExplicitlyRegisteredLocally;
}
}
_get = (type, name) => Get(type, name) ?? _parent._get(type, name);
_getGenericRegistration = GetOrAddGeneric;
_isTypeExplicitlyRegistered = IsTypeTypeExplicitlyRegisteredLocally;
_isExplicitlyRegistered = IsExplicitlyRegisteredLocally;
}
private void OnStrategiesChanged(object sender, EventArgs e)
@ -282,18 +289,18 @@ namespace Unity
var info = type.GetTypeInfo();
if (info.IsGenericType)
{
if (_isTypeExplicitlyRegistered(type)) return type;
if (IsTypeExplicitlyRegistered(type)) return type;
var definition = info.GetGenericTypeDefinition();
if (_isTypeExplicitlyRegistered(definition)) return definition;
if (IsTypeExplicitlyRegistered(definition)) return definition;
next = info.GenericTypeArguments[0];
if (_isTypeExplicitlyRegistered(next)) return next;
if (IsTypeExplicitlyRegistered(next)) return next;
}
else if (type.IsArray)
{
next = type.GetElementType();
if (_isTypeExplicitlyRegistered(next)) return next;
if (IsTypeExplicitlyRegistered(next)) return next;
}
else
{

Просмотреть файл

@ -23,7 +23,7 @@ namespace Unity
#region Registration Fields
private readonly object _syncRoot = new object();
internal readonly IPolicySet _defaults;
internal IPolicySet Defaults;
private HashRegistry<Type, IRegistry<string, IPolicySet>> _registrations;
#endregion
@ -31,16 +31,16 @@ namespace Unity
#region Default Registrations
private IPolicySet InitializeDefaultPolicies()
private void SetDefaultPolicies()
{
// Default policies
var defaults = new InternalRegistration(typeof(ResolveDelegate<BuilderContext>),
Defaults = new InternalRegistration(typeof(ResolveDelegate<BuilderContext>),
(ResolveDelegate<BuilderContext>)ExecuteDefaultPlan);
// Processors
var fieldsProcessor = new FieldsProcessor(defaults);
var methodsProcessor = new MethodsProcessor(defaults);
var propertiesProcessor = new PropertiesProcessor(defaults);
var constructorProcessor = new ConstructorProcessor(defaults, _isTypeExplicitlyRegistered);
var fieldsProcessor = new FieldsProcessor(Defaults);
var methodsProcessor = new MethodsProcessor(Defaults);
var propertiesProcessor = new PropertiesProcessor(Defaults);
var constructorProcessor = new ConstructorProcessor(Defaults, IsTypeExplicitlyRegistered);
// Processors chain
_processors = new StagedStrategyChain<BuildMemberProcessor, BuilderStage>
@ -55,13 +55,11 @@ namespace Unity
_processors.Invalidated += (s, e) => _processorsChain = _processors.ToArray();
_processorsChain = _processors.ToArray();
defaults.Set(typeof(ResolveDelegateFactory), (ResolveDelegateFactory)OptimizingFactory);
defaults.Set(typeof(ISelect<ConstructorInfo>), constructorProcessor);
defaults.Set(typeof(ISelect<FieldInfo>), fieldsProcessor);
defaults.Set(typeof(ISelect<PropertyInfo>), propertiesProcessor);
defaults.Set(typeof(ISelect<MethodInfo>), methodsProcessor);
return defaults;
Defaults.Set(typeof(ResolveDelegateFactory), (ResolveDelegateFactory)OptimizingFactory);
Defaults.Set(typeof(ISelect<ConstructorInfo>), constructorProcessor);
Defaults.Set(typeof(ISelect<FieldInfo>), fieldsProcessor);
Defaults.Set(typeof(ISelect<PropertyInfo>), propertiesProcessor);
Defaults.Set(typeof(ISelect<MethodInfo>), methodsProcessor);
}
#endregion
@ -106,10 +104,10 @@ namespace Unity
return candidate.Value
.Values
.Any(v => v is ContainerRegistration) ||
(_parent?._isTypeExplicitlyRegistered(type) ?? false);
(_parent?.IsTypeExplicitlyRegistered(type) ?? false);
}
return _parent?._isTypeExplicitlyRegistered(type) ?? false;
return _parent?.IsTypeExplicitlyRegistered(type) ?? false;
}
internal bool RegistrationExists(Type type, string name)
@ -149,9 +147,9 @@ namespace Unity
type = info.GetGenericTypeDefinition();
#else
if (!type.IsGenericType) return false;
if (!type?.IsGenericType ?? false) return false;
type = type.GetGenericTypeDefinition();
type = type?.GetGenericTypeDefinition();
#endif
hashCode = (type?.GetHashCode() ?? 0) & 0x7FFFFFFF;
for (var container = this; null != container; container = container._parent)

Просмотреть файл

@ -0,0 +1,17 @@
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Unity;
using Unity.Extension;
using Unity.Specification.Diagnostic.Constructor.Parameters;
namespace Constructor
{
[TestClass]
public class Parameters : SpecificationTests
{
public override IUnityContainer GetContainer()
{
return new UnityContainer()
.AddExtension(new Diagnostic());
}
}
}

Просмотреть файл

@ -0,0 +1,17 @@
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Unity;
using Unity.Extension;
using Unity.Specification.Diagnostic.Constructor.Types;
namespace Constructor
{
[TestClass]
public class Types : SpecificationTests
{
public override IUnityContainer GetContainer()
{
return new UnityContainer()
.AddExtension(new Diagnostic());
}
}
}

Просмотреть файл

@ -0,0 +1,19 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net461</TargetFramework>
<IsPackable>false</IsPackable>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="15.9.0" />
<PackageReference Include="MSTest.TestAdapter" Version="1.4.0" />
<PackageReference Include="MSTest.TestFramework" Version="1.4.0" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\..\SpecificationTests\diagnostic\Unity.Specification.Diagnostic.csproj" />
<ProjectReference Include="..\..\src\Unity.Container.csproj" />
</ItemGroup>
</Project>

Просмотреть файл

@ -1,7 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFrameworks>net46;netcoreapp2.0</TargetFrameworks>
<TargetFramework>net461</TargetFramework>
<IsPackable>false</IsPackable>
</PropertyGroup>
@ -12,7 +12,6 @@
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\..\Abstractions\src\Unity.Abstractions.csproj" />
<ProjectReference Include="..\..\..\SpecificationTests\src\Unity.Specification.csproj" />
<ProjectReference Include="..\..\src\Unity.Container.csproj" />
</ItemGroup>

Просмотреть файл

@ -1,39 +1,10 @@
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Unity.Exceptions;
using Unity.Injection;
namespace Unity.Tests.v5
{
[TestClass]
public class ConstructorWithOutAndRefParametersFixture
{
[TestMethod]
public void CanBuildUpExistingObjectOnTypeWithCtorWithRefParameter()
{
IUnityContainer container =
new UnityContainer()
.RegisterType<TypeWithConstructorWithRefParameter>(new InjectionProperty("Property", 10));
string ignored = "ignored";
TypeWithConstructorWithRefParameter instance = new TypeWithConstructorWithRefParameter(ref ignored);
container.BuildUp(instance);
Assert.AreEqual(10, instance.Property);
}
[TestMethod]
public void CanBuildUpExistingObjectOnTypeWithCtorWithOutParameter()
{
IUnityContainer container =
new UnityContainer()
.RegisterType<TypeWithConstructorWithOutParameter>(new InjectionProperty("Property", 10));
string ignored = "ignored";
TypeWithConstructorWithOutParameter instance = new TypeWithConstructorWithOutParameter(out ignored);
container.BuildUp(instance);
Assert.AreEqual(10, instance.Property);
}
[TestMethod]
public void ResolvingANewInstanceOfTypeWithCtorWithRefParameterThrows()

Просмотреть файл

@ -287,18 +287,6 @@ namespace Unity.Tests.v5.Container
AssertHelper.ThrowsException<ArgumentException>(() => uc.BuildUp(typeof(ChildStub1), objBase), "type of the object should match");
}
[TestMethod]
public void BuildBaseAndChildObject4()
{
UnityContainer uc = new UnityContainer();
BaseStub1 objBase = new BaseStub1();
Assert.IsNotNull(objBase);
Assert.IsNull(objBase.InterfaceProp);
uc.BuildUp(typeof(Interface1), objBase);
Assert.IsNotNull(objBase.InterfaceProp);
}
public interface Interface1
{
[Dependency]
@ -344,22 +332,6 @@ namespace Unity.Tests.v5.Container
#region BuildUp method with Abstract Base
[TestMethod]
public void BuildAbstractBaseAndChildObject1()
{
UnityContainer uc = new UnityContainer();
ConcreteChild objChild = new ConcreteChild();
Assert.IsNotNull(objChild);
Assert.IsNull(objChild.AbsBaseProp);
Assert.IsNull(objChild.ChildProp);
uc.BuildUp(typeof(AbstractBase), objChild);
Assert.IsNotNull(objChild.AbsBaseProp);
Assert.IsNull(objChild.ChildProp);
}
[TestMethod]
public void BuildAbstractBaseAndChildObject2()
{
@ -402,77 +374,6 @@ namespace Unity.Tests.v5.Container
#endregion
#region BuildUp method with Interface
[TestMethod]
public void BuildInterfacePropertyInjectTest1()
{
UnityContainer uc = new UnityContainer();
BarClass objBase = new BarClass();
uc.BuildUp(typeof(IFooInterface), objBase);
Assert.IsNotNull(objBase.InterfaceProp);
}
[TestMethod]
public void BuildInterfacePropertyInjectTest2()
{
UnityContainer uc = new UnityContainer();
BarClass2 objBase = new BarClass2();
uc.BuildUp(typeof(IFooInterface2), objBase);
Assert.IsNull(objBase.InterfaceProp);
}
public interface IFooInterface
{
[Dependency]
object InterfaceProp
{
get;
set;
}
}
public interface IFooInterface2
{
object InterfaceProp
{
get;
set;
}
}
public class BarClass : IFooInterface
{
public object InterfaceProp { get; set; }
}
public class BarClass2 : IFooInterface2
{
[Dependency]
public object InterfaceProp { get; set; }
}
public class PropertyDependencyClassStub1
{
[Dependency]
public object MyFirstObj { get; set; }
}
public class PropertyDependencyClassStub2
{
[Dependency]
public object MyFirstObj { get; set; }
[Dependency]
public object MySecondObj { get; set; }
}
#endregion
#region BuildUp method with Contained Object
[TestMethod]

Просмотреть файл

@ -264,31 +264,6 @@ namespace Unity.Tests.v5
Assert.IsInstanceOfType(o.Logger, typeof(MockLogger));
}
[TestMethod]
public void CanBuildupObjectWithExplicitInterface()
{
var container = new UnityContainer()
.RegisterType<ILogger, MockLogger>();
var o = new ObjectWithExplicitInterface();
container.BuildUp<ISomeCommonProperties>(o);
o.ValidateInterface();
}
[TestMethod]
public void CanBuildupObjectWithExplicitInterfaceUsingNongenericMethod()
{
var container = new UnityContainer()
.RegisterType<ILogger, MockLogger>();
var o = new ObjectWithExplicitInterface();
container.BuildUp(typeof(ISomeCommonProperties), o);
o.ValidateInterface();
}
[TestMethod]
public void CanUseInstanceAsSingleton()
{