Added Diagnostic set of tests
This commit is contained in:
Родитель
7a48052787
Коммит
7adb340019
|
@ -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()
|
||||
{
|
||||
|
|
Загрузка…
Ссылка в новой задаче