Skip to content

Commit 5f01533

Browse files
committed
Merge branch 'master' of https://github.com/unitycontainer/container into v5.x
2 parents e839eba + c4c004a commit 5f01533

File tree

6 files changed

+102
-23
lines changed

6 files changed

+102
-23
lines changed

src/Builder/Context/BuilderContext.cs

Lines changed: 30 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
using System.Reflection;
44
using System.Runtime.CompilerServices;
55
using System.Security;
6+
using Unity.Exceptions;
67
using Unity.Lifetime;
78
using Unity.Policy;
89
using Unity.Registration;
@@ -24,6 +25,7 @@ public struct BuilderContext : IResolveContext
2425
public IPolicyList List;
2526

2627
public delegate object ExecutePlanDelegate(BuilderStrategy[] chain, ref BuilderContext context);
28+
public delegate object ResolvePlanDelegate(ref BuilderContext context, ResolveDelegate<BuilderContext> resolver);
2729

2830
#endregion
2931

@@ -57,7 +59,7 @@ public object Resolve(Type type, string name)
5759
{
5860
var context = this;
5961

60-
return resolverPolicy.Resolve(ref context);
62+
return ResolvePlan(ref context, resolverPolicy.Resolve);
6163
}
6264
}
6365
}
@@ -127,6 +129,8 @@ public void Clear(Type type, string name, Type policyInterface)
127129
#endif
128130
public ExecutePlanDelegate ExecutePlan;
129131

132+
public ResolvePlanDelegate ResolvePlan;
133+
130134
#endregion
131135

132136

@@ -145,6 +149,7 @@ public object Resolve(Type type, string name, InternalRegistration registration)
145149
Name = name,
146150
Type = registration is ContainerRegistration containerRegistration ? containerRegistration.Type : type,
147151
ExecutePlan = ExecutePlan,
152+
ResolvePlan = ResolvePlan,
148153
List = List,
149154
Overrides = Overrides,
150155
DeclaringType = Type,
@@ -175,14 +180,14 @@ public object Resolve(ParameterInfo parameter, object value)
175180
// Check if itself is a value
176181
if (resolverOverride is IResolve resolverPolicy)
177182
{
178-
return resolverPolicy.Resolve(ref context);
183+
return ResolvePlan(ref context, resolverPolicy.Resolve);
179184
}
180185

181186
// Try to create value
182187
var resolveDelegate = resolverOverride.GetResolver<BuilderContext>(parameter.ParameterType);
183188
if (null != resolveDelegate)
184189
{
185-
return resolveDelegate(ref context);
190+
return ResolvePlan(ref context, resolveDelegate);
186191
}
187192
}
188193
}
@@ -220,14 +225,14 @@ public object Resolve(PropertyInfo property, object value)
220225
// Check if itself is a value
221226
if (resolverOverride is IResolve resolverPolicy)
222227
{
223-
return resolverPolicy.Resolve(ref context);
228+
return ResolvePlan(ref context, resolverPolicy.Resolve);
224229
}
225230

226231
// Try to create value
227232
var resolveDelegate = resolverOverride.GetResolver<BuilderContext>(property.PropertyType);
228233
if (null != resolveDelegate)
229234
{
230-
return resolveDelegate(ref context);
235+
return ResolvePlan(ref context, resolveDelegate);
231236
}
232237
}
233238
}
@@ -240,8 +245,15 @@ public object Resolve(PropertyInfo property, object value)
240245
return Resolve(property.PropertyType, dependencyAttribute.Name);
241246

242247
case OptionalDependencyAttribute optionalAttribute:
243-
try { return Resolve(property.PropertyType, optionalAttribute.Name); }
244-
catch { return null; }
248+
try
249+
{
250+
return Resolve(property.PropertyType, optionalAttribute.Name);
251+
}
252+
catch (Exception ex)
253+
when (!(ex.InnerException is CircularDependencyException))
254+
{
255+
return null;
256+
}
245257

246258
case ResolveDelegate<BuilderContext> resolver:
247259
return resolver(ref context);
@@ -268,14 +280,14 @@ public object Resolve(FieldInfo field, object value)
268280
// Check if itself is a value
269281
if (resolverOverride is IResolve resolverPolicy)
270282
{
271-
return resolverPolicy.Resolve(ref context);
283+
return ResolvePlan(ref context, resolverPolicy.Resolve);
272284
}
273285

274286
// Try to create value
275287
var resolveDelegate = resolverOverride.GetResolver<BuilderContext>(field.FieldType);
276288
if (null != resolveDelegate)
277289
{
278-
return resolveDelegate(ref context);
290+
return ResolvePlan(ref context, resolveDelegate);
279291
}
280292
}
281293
}
@@ -288,8 +300,15 @@ public object Resolve(FieldInfo field, object value)
288300
return Resolve(field.FieldType, dependencyAttribute.Name);
289301

290302
case OptionalDependencyAttribute optionalAttribute:
291-
try { return Resolve(field.FieldType, optionalAttribute.Name); }
292-
catch { return null; }
303+
try
304+
{
305+
return Resolve(field.FieldType, optionalAttribute.Name);
306+
}
307+
catch (Exception ex)
308+
when (!(ex.InnerException is CircularDependencyException))
309+
{
310+
return null;
311+
}
293312

294313
case ResolveDelegate<BuilderContext> resolver:
295314
return resolver(ref context);

src/Processors/Abstracts/MemberProcessor.cs

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -263,7 +263,7 @@ public TPolicyInterface GetPolicy<TPolicyInterface>(IPolicySet registration)
263263
#endregion
264264

265265

266-
#region Parameter Resolver Factories
266+
#region Attribute Resolver Factories
267267

268268
protected virtual ResolveDelegate<BuilderContext> DependencyResolverFactory(Attribute attribute, object info, object value = null)
269269
{
@@ -276,8 +276,15 @@ protected virtual ResolveDelegate<BuilderContext> OptionalDependencyResolverFact
276276
var type = MemberType((TMemberInfo)info);
277277
return (ref BuilderContext context) =>
278278
{
279-
try { return context.Resolve(type, ((DependencyResolutionAttribute)attribute).Name); }
280-
catch { return value; }
279+
try
280+
{
281+
return context.Resolve(type, ((DependencyResolutionAttribute)attribute).Name);
282+
}
283+
catch (Exception ex)
284+
when (!(ex.InnerException is CircularDependencyException))
285+
{
286+
return value;
287+
}
281288
};
282289
}
283290

src/Processors/Parameters/ParametersProcessor.cs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
using System.Linq.Expressions;
44
using System.Reflection;
55
using Unity.Builder;
6+
using Unity.Exceptions;
67
using Unity.Policy;
78
using Unity.Resolution;
89

@@ -201,7 +202,8 @@ protected override ResolveDelegate<BuilderContext> OptionalDependencyResolverFac
201202
{
202203
return context.Resolve(((ParameterInfo)info).ParameterType, ((DependencyResolutionAttribute)attribute).Name);
203204
}
204-
catch
205+
catch (Exception ex)
206+
when (!(ex.InnerException is CircularDependencyException))
205207
{
206208
return value;
207209
}

src/UnityContainer.IUnityContainer.cs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -244,6 +244,7 @@ object IUnityContainer.Resolve(Type type, string name, params ResolverOverride[]
244244
RegistrationType = type,
245245
Name = name,
246246
ExecutePlan = ContextExecutePlan,
247+
ResolvePlan = ContextResolvePlan,
247248
Type = registration is ContainerRegistration containerRegistration
248249
? containerRegistration.Type : type,
249250
};
@@ -276,6 +277,7 @@ object IUnityContainer.BuildUp(Type type, object existing, string name, params R
276277
RegistrationType = type,
277278
Name = name,
278279
ExecutePlan = ContextExecutePlan,
280+
ResolvePlan = ContextResolvePlan,
279281
Type = registration is ContainerRegistration containerRegistration
280282
? containerRegistration.Type : type
281283
};

src/UnityContainer.Implementation.cs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -160,7 +160,8 @@ private UnityContainer(UnityContainer parent)
160160
internal static void SetDiagnosticPolicies(UnityContainer container)
161161
{
162162
// Default policies
163-
container.ContextExecutePlan = UnityContainer.ContextValidatingPlan;
163+
container.ContextExecutePlan = UnityContainer.ContextValidatingExecutePlan;
164+
container.ContextResolvePlan = UnityContainer.ContextValidatingResolvePlan;
164165
container.ExecutePlan = container.ExecuteValidatingPlan;
165166
container.Defaults = new InternalRegistration(typeof(BuilderContext.ExecutePlanDelegate), container.ContextExecutePlan);
166167
if (null != container._registrations) container.Set(null, null, container.Defaults);

src/UnityContainer.Resolution.cs

Lines changed: 55 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -274,7 +274,6 @@ private ResolveDelegate<BuilderContext> ResolvingFactory(ref BuilderContext cont
274274
return context.Existing;
275275
};
276276

277-
278277
private object ExecuteValidatingPlan(ref BuilderContext context)
279278
{
280279
var i = -1;
@@ -363,6 +362,11 @@ string CreateErrorMessage(object value)
363362
}
364363
}
365364

365+
#endregion
366+
367+
368+
#region BuilderContext
369+
366370
internal BuilderContext.ExecutePlanDelegate ContextExecutePlan { get; set; } =
367371
(BuilderStrategy[] chain, ref BuilderContext context) =>
368372
{
@@ -389,7 +393,7 @@ string CreateErrorMessage(object value)
389393
return context.Existing;
390394
};
391395

392-
internal static object ContextValidatingPlan(BuilderStrategy[] chain, ref BuilderContext context)
396+
internal static object ContextValidatingExecutePlan(BuilderStrategy[] chain, ref BuilderContext context)
393397
{
394398
var i = -1;
395399
#if !NET40
@@ -430,20 +434,64 @@ object GetPerResolveValue(IntPtr parent, Type registrationType, string name)
430434

431435
unsafe
432436
{
433-
var c = Unsafe.AsRef<BuilderContext>(parent.ToPointer());
434-
if (registrationType != c.RegistrationType || name != c.Name)
435-
return GetPerResolveValue(c.Parent, registrationType, name);
437+
var parentRef = Unsafe.AsRef<BuilderContext>(parent.ToPointer());
438+
if (registrationType != parentRef.RegistrationType || name != parentRef.Name)
439+
return GetPerResolveValue(parentRef.Parent, registrationType, name);
436440

437-
var lifetimeManager = (LifetimeManager)c.Get(typeof(LifetimeManager));
441+
var lifetimeManager = (LifetimeManager)parentRef.Get(typeof(LifetimeManager));
438442
var result = lifetimeManager?.GetValue();
439443
if (null != result) return result;
440444

441-
throw new InvalidOperationException($"Circular reference for type: {c.Type}");
445+
throw new InvalidOperationException($"Circular reference for Type: {parentRef.Type}, Name: {parentRef.Name}",
446+
new CircularDependencyException());
442447
}
443448
}
444449
#endif
445450
}
446451

452+
internal BuilderContext.ResolvePlanDelegate ContextResolvePlan { get; set; } =
453+
(ref BuilderContext context, ResolveDelegate<BuilderContext> resolver) => resolver(ref context);
454+
455+
internal static object ContextValidatingResolvePlan(ref BuilderContext thisContext, ResolveDelegate<BuilderContext> resolver)
456+
{
457+
if (null == resolver) throw new ArgumentNullException(nameof(resolver));
458+
459+
#if NET40
460+
return resolver(ref thisContext);
461+
#else
462+
unsafe
463+
{
464+
var parent = thisContext.Parent;
465+
while(IntPtr.Zero != parent)
466+
{
467+
var parentRef = Unsafe.AsRef<BuilderContext>(parent.ToPointer());
468+
if (thisContext.RegistrationType == parentRef.RegistrationType && thisContext.Name == parentRef.Name)
469+
throw new InvalidOperationException($"Circular reference for Type: {thisContext.Type}, Name: {thisContext.Name}",
470+
new CircularDependencyException());
471+
472+
parent = parentRef.Parent;
473+
}
474+
475+
var context = new BuilderContext
476+
{
477+
Lifetime = thisContext.Lifetime,
478+
Registration = thisContext.Registration,
479+
RegistrationType = thisContext.Type,
480+
Name = thisContext.Name,
481+
Type = thisContext.Type,
482+
ExecutePlan = thisContext.ExecutePlan,
483+
ResolvePlan = thisContext.ResolvePlan,
484+
List = thisContext.List,
485+
Overrides = thisContext.Overrides,
486+
DeclaringType = thisContext.Type,
487+
Parent = new IntPtr(Unsafe.AsPointer(ref thisContext))
488+
};
489+
490+
return resolver(ref context);
491+
}
492+
#endif
493+
}
494+
447495
#endregion
448496
}
449497
}

0 commit comments

Comments
 (0)