Skip to content

Commit 1ce7a54

Browse files
committed
Fixed tests
1 parent b0c6918 commit 1ce7a54

File tree

18 files changed

+358
-158
lines changed

18 files changed

+358
-158
lines changed

src/Processors/Abstracts/MemberExpression.cs

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,15 +31,13 @@ protected virtual IEnumerable<Expression> ExpressionsFromSelection(Type type, IE
3131

3232
yield return GetResolverExpression(info, value);
3333
break;
34-
3534

3635
// Injection Member
3736
case InjectionMember<TMemberInfo, TData> injectionMember:
3837
yield return GetResolverExpression(injectionMember.MemberInfo(type),
3938
injectionMember.Data);
4039
break;
4140

42-
4341
// Unknown
4442
default:
4543
throw new InvalidOperationException($"Unknown MemberInfo<{typeof(TMemberInfo)}> type");

src/Processors/Constructor/ConstructorExpression.cs

Lines changed: 16 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
using System.Linq.Expressions;
55
using System.Reflection;
66
using Unity.Builder;
7+
using Unity.Exceptions;
78
using Unity.Injection;
89
using Unity.Lifetime;
910
using Unity.Policy;
@@ -96,13 +97,21 @@ protected override Expression GetResolverExpression(ConstructorInfo info, object
9697
var variable = Expression.Variable(info.DeclaringType);
9798
var parametersExpr = CreateParameterExpressions(info.GetParameters(), resolvers);
9899

99-
return Expression.IfThen(
100-
Expression.Equal(Expression.Constant(null), BuilderContextExpression.Existing),
101-
Expression.Block(new[] { variable }, new Expression[]
102-
{
103-
Expression.Assign(variable, Expression.New(info, parametersExpr)),
104-
Expression.Assign(BuilderContextExpression.Existing, Expression.Convert(variable, typeof(object)))
105-
}));
100+
try
101+
{
102+
return Expression.IfThen(
103+
Expression.Equal(Expression.Constant(null), BuilderContextExpression.Existing),
104+
Expression.Block(new[] { variable }, new Expression[]
105+
{
106+
Expression.Assign(variable, Expression.New(info, parametersExpr)),
107+
Expression.Assign(BuilderContextExpression.Existing, Expression.Convert(variable, typeof(object)))
108+
}));
109+
}
110+
catch (ArgumentException ex)
111+
{
112+
throw new InvalidRegistrationException("Invalid Argument", ex);
113+
}
114+
106115
}
107116

108117
#endregion

src/Processors/Methods/MethodProcessor.cs

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
using System.Linq.Expressions;
55
using System.Reflection;
66
using Unity.Builder;
7+
using Unity.Exceptions;
78
using Unity.Policy;
89
using Unity.Resolution;
910

@@ -37,9 +38,16 @@ protected override IEnumerable<MethodInfo> DeclaredMembers(Type type)
3738

3839
protected override Expression GetResolverExpression(MethodInfo info, object resolvers)
3940
{
40-
return Expression.Call(
41-
Expression.Convert(BuilderContextExpression.Existing, info.DeclaringType),
42-
info, CreateParameterExpressions(info.GetParameters(), resolvers));
41+
try
42+
{
43+
return Expression.Call(
44+
Expression.Convert(BuilderContextExpression.Existing, info.DeclaringType),
45+
info, CreateParameterExpressions(info.GetParameters(), resolvers));
46+
}
47+
catch (ArgumentException ex)
48+
{
49+
throw new InvalidRegistrationException("Invalid Argument", ex);
50+
}
4351
}
4452

4553
#endregion

src/Storage/RegistrationSet.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -48,13 +48,13 @@ public ref Entry this[int index]
4848

4949
public void Add(Type type, string name, InternalRegistration registration)
5050
{
51-
var hashCode = ((type?.GetHashCode() ?? 0 + 37) ^ (name?.GetHashCode() ?? 0 + 17)) & 0x7FFFFFFF;
51+
var hashCode = (37 ^ (name?.GetHashCode() ?? 0 + 17)) & 0x7FFFFFFF;
5252
var bucket = hashCode % _buckets.Length;
5353
var collisionCount = 0;
5454
for (int i = _buckets[bucket]; --i >= 0; i = _entries[i].Next)
5555
{
5656
ref var entry = ref _entries[i];
57-
if (entry.HashCode == hashCode && entry.RegisteredType == type)
57+
if (entry.HashCode == hashCode && entry.Name == name)
5858
{
5959
entry.RegisteredType = type;
6060
entry.Name = name;

src/Strategies/BuildPlanStrategy.cs

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
using System.Linq;
44
using System.Reflection;
55
using Unity.Builder;
6+
using Unity.Exceptions;
67
using Unity.Injection;
78
using Unity.Lifetime;
89
using Unity.Policy;
@@ -47,16 +48,21 @@ public override void PreBuildUp(ref BuilderContext context)
4748
if (null == resolver)
4849
{
4950
// Check if can create at all
50-
if (!(context.Registration is ContainerRegistration) &&
51+
5152
#if NETCOREAPP1_0 || NETSTANDARD1_0
52-
context.RegistrationType.GetTypeInfo().IsGenericTypeDefinition)
53+
if (!(context.Registration is ContainerRegistration) && context.RegistrationType.GetTypeInfo().IsGenericTypeDefinition)
5354
#else
54-
context.RegistrationType.IsGenericTypeDefinition)
55+
if (!(context.Registration is ContainerRegistration) && context.RegistrationType.IsGenericTypeDefinition)
5556
#endif
5657
{
5758
throw new ArgumentException(string.Format(CultureInfo.CurrentCulture,
5859
"The type {0} is an open generic type. An open generic type cannot be resolved.",
59-
context.RegistrationType.FullName));
60+
context.RegistrationType.FullName), new InvalidRegistrationException());
61+
}
62+
else if (context.Type.IsArray && context.Type.GetArrayRank() > 1)
63+
{
64+
var message = $"Invalid array {context.Type}. Only arrays of rank 1 are supported";
65+
throw new ArgumentException(message, new InvalidRegistrationException());
6066
}
6167

6268
// Get resolver factory

src/UnityContainer.Diagnostic.cs

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,10 @@
11
using System;
2+
using System.Collections;
23
using System.Collections.Generic;
34
using System.Diagnostics;
45
using System.Linq;
6+
using System.Reflection;
7+
using System.Text;
58
using Unity.Policy;
69
using Unity.Registration;
710

@@ -18,6 +21,64 @@ public partial class UnityContainer
1821
#endregion
1922

2023

24+
#region Error Message
25+
26+
private static Func<Exception, string> CreateMessage = (Exception ex) =>
27+
{
28+
return $"Resolution failed with error: {ex.Message}\n\nFor more detailed information run Unity in debug mode: new UnityContainer(ModeFlags.Diagnostic)";
29+
};
30+
31+
private static string CreateDiagnosticMessage(Exception ex)
32+
{
33+
const string line = "_____________________________________________________";
34+
35+
var builder = new StringBuilder();
36+
builder.AppendLine(ex.Message);
37+
builder.AppendLine(line);
38+
builder.AppendLine("Exception occurred while:");
39+
40+
foreach (DictionaryEntry item in ex.Data)
41+
builder.AppendLine(DataToString(item.Value));
42+
43+
return builder.ToString();
44+
}
45+
46+
private static string DataToString(object value)
47+
{
48+
switch (value)
49+
{
50+
case ParameterInfo parameter:
51+
return $" for parameter: {parameter.Name}";
52+
53+
case ConstructorInfo constructor:
54+
var ctorSignature = string.Join(", ", constructor.GetParameters().Select(p => $"{p.ParameterType.Name} {p.Name}"));
55+
return $" on constructor: {constructor.DeclaringType.Name}({ctorSignature})";
56+
57+
case MethodInfo method:
58+
var methodSignature = string.Join(", ", method.GetParameters().Select(p => $"{p.ParameterType.Name} {p.Name}"));
59+
return $" on method: {method.Name}({methodSignature})";
60+
61+
case PropertyInfo property:
62+
return $" for property: {property.Name}";
63+
64+
case FieldInfo field:
65+
return $" for field: {field.Name}";
66+
67+
case Type type:
68+
return $"\n• while resolving: {type.Name}";
69+
70+
case Tuple<Type, string> tuple:
71+
return $"\n• while resolving: {tuple.Item1.Name} registered with name: {tuple.Item2}";
72+
73+
case Tuple<Type, Type> tuple:
74+
return $" mapped to: {tuple.Item1?.Name}";
75+
}
76+
77+
return value.ToString();
78+
}
79+
#endregion
80+
81+
2182
#region Debug Support
2283

2384
private string DebugName()

src/UnityContainer.IUnityContainer.cs

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -27,20 +27,20 @@ public partial class UnityContainer : IUnityContainer
2727
/// <inheritdoc />
2828
IUnityContainer IUnityContainer.RegisterType(Type typeFrom, Type typeTo, string name, ITypeLifetimeManager lifetimeManager, InjectionMember[] injectionMembers)
2929
{
30+
var mappedToType = typeTo;
31+
var registeredType = typeFrom ?? typeTo;
32+
if (null == registeredType) throw new ArgumentNullException(nameof(typeTo));
33+
34+
// Validate if they are assignable
35+
TypeValidator?.Invoke(typeFrom, typeTo);
36+
3037
try
3138
{
32-
var mappedToType = typeTo;
33-
var registeredType = typeFrom ?? typeTo;
3439
LifetimeManager manager = (null != lifetimeManager)
3540
? (LifetimeManager)lifetimeManager
3641
: TypeLifetimeManager.CreateLifetimePolicy();
37-
// Validate input
38-
if (null == typeTo) throw new ArgumentNullException(nameof(typeTo));
3942
if (manager.InUse) throw new InvalidOperationException(LifetimeManagerInUse);
4043

41-
// Validate if they are assignable
42-
TypeValidator?.Invoke(typeFrom, typeTo);
43-
4444
// Create registration and add to appropriate storage
4545
var container = manager is SingletonLifetimeManager ? _root : this;
4646
var registration = new ContainerRegistration(_validators, typeTo, manager, injectionMembers);
@@ -232,7 +232,6 @@ object IUnityContainer.Resolve(Type type, string name, params ResolverOverride[]
232232
{
233233
// Verify arguments
234234
if (null == type) throw new ArgumentNullException(nameof(type));
235-
name = string.IsNullOrEmpty(name) ? null : name;
236235

237236
var registration = (InternalRegistration)GetRegistration(type, name);
238237
var context = new BuilderContext

src/UnityContainer.Implementation.cs

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -213,14 +213,26 @@ internal static void SetDiagnosticPolicies(UnityContainer container)
213213
var infoFrom = typeFrom.GetTypeInfo();
214214
var infoTo = typeTo.GetTypeInfo();
215215

216-
if (typeFrom != null && !infoFrom.IsGenericType && !infoTo.IsGenericType && !infoFrom.IsAssignableFrom(infoTo))
216+
if (null != typeFrom && typeFrom != null && !infoFrom.IsGenericType &&
217+
null != typeTo && !infoTo.IsGenericType && !infoFrom.IsAssignableFrom(infoTo))
217218
#else
218-
if (typeFrom != null && !typeFrom.IsGenericType && !typeTo.IsGenericType && !typeFrom.IsAssignableFrom(typeTo))
219+
if (null != typeFrom && typeFrom != null && !typeFrom.IsGenericType &&
220+
null != typeTo && !typeTo.IsGenericType && !typeFrom.IsAssignableFrom(typeTo))
219221
#endif
220222
{
221223
throw new ArgumentException($"The type {typeTo} cannot be assigned to variables of type {typeFrom}.");
222224
}
223225

226+
#if NETSTANDARD1_0 || NETCOREAPP1_0
227+
if (null != typeFrom && null != typeTo && infoFrom.IsGenericType && infoTo.IsArray &&
228+
infoFrom.GetGenericTypeDefinition() == typeof(IEnumerable<>))
229+
#else
230+
if (null != typeFrom && null != typeTo && typeFrom.IsGenericType && typeTo.IsArray &&
231+
typeFrom.GetGenericTypeDefinition() == typeof(IEnumerable<>))
232+
#endif
233+
throw new ArgumentException($"Type mapping of IEnumerable<T> to array T[] is not supported.");
234+
235+
224236
#if NETSTANDARD1_0 || NETCOREAPP1_0
225237
if (null == typeFrom && infoTo.IsInterface)
226238
#else

src/UnityContainer.Resolution.cs

Lines changed: 12 additions & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -353,8 +353,14 @@ internal ResolveDelegate<BuilderContext> ResolvingFactory(ref BuilderContext con
353353
{
354354
context.RequiresRecovery?.Recover();
355355

356-
throw new ResolutionFailedException(context.RegistrationType, context.Name,
357-
"For more information add Diagnostic extension: Container.AddExtension(new Diagnostic())", ex);
356+
if (!(ex.InnerException is InvalidRegistrationException) &&
357+
!(ex is InvalidRegistrationException) &&
358+
!(ex is ObjectDisposedException) &&
359+
!(ex is MemberAccessException) &&
360+
!(ex is MakeGenericTypeFailedException))
361+
throw;
362+
363+
throw new ResolutionFailedException(context.RegistrationType, context.Name, CreateMessage(ex), ex);
358364
}
359365

360366
return context.Existing;
@@ -380,6 +386,7 @@ private object ExecuteValidatingPlan(ref BuilderContext context)
380386
catch (Exception ex)
381387
{
382388
context.RequiresRecovery?.Recover();
389+
383390
ex.Data.Add(Guid.NewGuid(), null == context.Name
384391
? context.RegistrationType == context.Type
385392
? (object)context.Type
@@ -388,64 +395,12 @@ private object ExecuteValidatingPlan(ref BuilderContext context)
388395
? (object)new Tuple<Type, string>(context.Type, context.Name)
389396
: new Tuple<Type, Type, string>(context.RegistrationType, context.Type, context.Name));
390397

391-
var builder = new StringBuilder();
392-
builder.AppendLine(ex.Message);
393-
builder.AppendLine("_____________________________________________________");
394-
builder.AppendLine("Exception occurred while:");
395-
builder.AppendLine();
396-
397-
var indent = 0;
398-
foreach (DictionaryEntry item in ex.Data)
399-
{
400-
for (var c = 0; c < indent; c++) builder.Append(" ");
401-
builder.AppendLine(CreateErrorMessage(item.Value));
402-
indent += 1;
403-
}
404-
405-
var message = builder.ToString();
398+
var message = CreateDiagnosticMessage(ex);
406399

407400
throw new ResolutionFailedException( context.RegistrationType, context.Name, message, ex);
408401
}
409402

410403
return context.Existing;
411-
412-
413-
string CreateErrorMessage(object value)
414-
{
415-
switch (value)
416-
{
417-
case ParameterInfo parameter:
418-
return $" for parameter: '{parameter.Name}'";
419-
420-
case ConstructorInfo constructor:
421-
var ctorSignature = string.Join(", ", constructor.GetParameters().Select(p => $"{p.ParameterType.Name} {p.Name}"));
422-
return $"on constructor: {constructor.DeclaringType.Name}({ctorSignature})";
423-
424-
case MethodInfo method:
425-
var methodSignature = string.Join(", ", method.GetParameters().Select(p => $"{p.ParameterType.Name} {p.Name}"));
426-
return $" on method: {method.Name}({methodSignature})";
427-
428-
case PropertyInfo property:
429-
return $" for property: '{property.Name}'";
430-
431-
case FieldInfo field:
432-
return $" for field: '{field.Name}'";
433-
434-
case Type type:
435-
return $"·resolving type: '{type.Name}'";
436-
437-
case Tuple<Type, string> tuple:
438-
return $"•resolving type: '{tuple.Item1.Name}' registered with name: '{tuple.Item2}'";
439-
440-
case Tuple<Type, Type> tuple:
441-
return $"•resolving type: '{tuple.Item1?.Name}' mapped to '{tuple.Item2?.Name}'";
442-
443-
case Tuple<Type, Type, string> tuple:
444-
return $"•resolving type: '{tuple.Item1?.Name}' mapped to '{tuple.Item2?.Name}' and registered with name: '{tuple.Item3}'";
445-
}
446-
447-
return value.ToString();
448-
}
449404
}
450405

451406
#endregion
@@ -529,7 +484,7 @@ object GetPerResolveValue(IntPtr parent, Type registrationType, string name)
529484
if (LifetimeManager.NoValue != result) return result;
530485

531486
throw new InvalidOperationException($"Circular reference for Type: {parentRef.Type}, Name: {parentRef.Name}",
532-
new CircularDependencyException());
487+
new CircularDependencyException(parentRef.Type, parentRef.Name));
533488
}
534489
}
535490
#endif
@@ -552,8 +507,7 @@ internal static object ContextValidatingResolvePlan(ref BuilderContext thisConte
552507
{
553508
var parentRef = Unsafe.AsRef<BuilderContext>(parent.ToPointer());
554509
if (thisContext.RegistrationType == parentRef.RegistrationType && thisContext.Name == parentRef.Name)
555-
throw new InvalidOperationException($"Circular reference for Type: {thisContext.Type}, Name: {thisContext.Name}",
556-
new CircularDependencyException());
510+
throw new CircularDependencyException(thisContext.Type, thisContext.Name);
557511

558512
parent = parentRef.Parent;
559513
}

0 commit comments

Comments
 (0)