diff --git a/src/Autofac/Core/ISharingLifetimeScope.cs b/src/Autofac/Core/ISharingLifetimeScope.cs
index 004bebe81..2395cc34c 100644
--- a/src/Autofac/Core/ISharingLifetimeScope.cs
+++ b/src/Autofac/Core/ISharingLifetimeScope.cs
@@ -55,8 +55,11 @@ public interface ISharingLifetimeScope : ILifetimeScope
/// possible secondary qualifying GUID key.
///
/// Key to look up.
- /// Secondary key to look up.
- /// The instance that has the specified key.
+ ///
+ /// Secondary key to look up, to better identify an instance that wraps around another instance
+ /// or is otherwise "namespaced" by it.
+ ///
+ /// The instance that has the specified keys.
/// true if the key was found; otherwise, false .
bool TryGetSharedInstance(Guid primaryId, Guid? qualifyingId, out object value);
@@ -73,7 +76,10 @@ public interface ISharingLifetimeScope : ILifetimeScope
/// possible secondary qualifying GUID key.
///
/// Key.
- /// Secondary key.
+ ///
+ /// Secondary key, to better identify an instance that wraps around another instance
+ /// or is otherwise "namespaced" by it.
+ ///
/// A function that will create the instance when called.
/// The shared instance.
object CreateSharedInstance(Guid primaryId, Guid? qualifyingId, Func creator);
diff --git a/src/Autofac/Core/Lifetime/LifetimeScope.cs b/src/Autofac/Core/Lifetime/LifetimeScope.cs
index 01429fb00..c7d02abc4 100644
--- a/src/Autofac/Core/Lifetime/LifetimeScope.cs
+++ b/src/Autofac/Core/Lifetime/LifetimeScope.cs
@@ -48,7 +48,8 @@ public class LifetimeScope : Disposable, ISharingLifetimeScope, IServiceProvider
/// Protects shared instances from concurrent access. Other members and the base class are threadsafe.
///
private readonly object _synchRoot = new object();
- private readonly ConcurrentDictionary<(Guid, Guid?), object> _sharedInstances = new ConcurrentDictionary<(Guid, Guid?), object>();
+ private readonly ConcurrentDictionary _sharedInstances = new ConcurrentDictionary();
+ private readonly ConcurrentDictionary<(Guid, Guid), object> _sharedQualifiedInstances = new ConcurrentDictionary<(Guid, Guid), object>();
private object? _anonymousTag;
private LifetimeScope? parentScope;
@@ -82,7 +83,7 @@ protected LifetimeScope(IComponentRegistry componentRegistry, LifetimeScope pare
/// Components used in the scope.
public LifetimeScope(IComponentRegistry componentRegistry, object tag)
{
- _sharedInstances[(SelfRegistrationId, null)] = this;
+ _sharedInstances[SelfRegistrationId] = this;
ComponentRegistry = componentRegistry ?? throw new ArgumentNullException(nameof(componentRegistry));
Tag = tag ?? throw new ArgumentNullException(nameof(tag));
RootLifetimeScope = this;
@@ -292,35 +293,56 @@ public object ResolveComponent(ResolveRequest request)
///
public object CreateSharedInstance(Guid id, Func creator)
{
- return CreateSharedInstance(id, null, creator);
+ if (creator == null) throw new ArgumentNullException(nameof(creator));
+ lock (_synchRoot)
+ {
+ if (_sharedInstances.TryGetValue(id, out var result)) return result;
+
+ result = creator();
+ if (_sharedInstances.ContainsKey(id))
+ throw new DependencyResolutionException(string.Format(CultureInfo.CurrentCulture, LifetimeScopeResources.SelfConstructingDependencyDetected, result.GetType().FullName));
+
+ _sharedInstances.TryAdd(id, result);
+
+ return result;
+ }
}
///
public object CreateSharedInstance(Guid primaryId, Guid? qualifyingId, Func creator)
{
if (creator == null) throw new ArgumentNullException(nameof(creator));
+ if (qualifyingId == null)
+ {
+ return CreateSharedInstance(primaryId, creator);
+ }
lock (_synchRoot)
{
- var instanceKey = (primaryId, qualifyingId);
+ var instanceKey = (primaryId, qualifyingId.Value);
- if (_sharedInstances.TryGetValue(instanceKey, out var result)) return result;
+ if (_sharedQualifiedInstances.TryGetValue(instanceKey, out var result)) return result;
result = creator();
- if (_sharedInstances.ContainsKey(instanceKey))
+ if (_sharedQualifiedInstances.ContainsKey(instanceKey))
throw new DependencyResolutionException(string.Format(CultureInfo.CurrentCulture, LifetimeScopeResources.SelfConstructingDependencyDetected, result.GetType().FullName));
- _sharedInstances.TryAdd(instanceKey, result);
+ _sharedQualifiedInstances.TryAdd(instanceKey, result);
return result;
}
}
///
- public bool TryGetSharedInstance(Guid id, out object value) => TryGetSharedInstance(id, null, out value);
+ public bool TryGetSharedInstance(Guid id, out object value) => _sharedInstances.TryGetValue(id, out value);
///
- public bool TryGetSharedInstance(Guid primaryId, Guid? qualifyingId, out object value) => _sharedInstances.TryGetValue((primaryId, qualifyingId), out value);
+ public bool TryGetSharedInstance(Guid primaryId, Guid? qualifyingId, out object value)
+ {
+ return qualifyingId == null
+ ? TryGetSharedInstance(primaryId, out value)
+ : _sharedQualifiedInstances.TryGetValue((primaryId, qualifyingId.Value), out value);
+ }
///
/// Gets the disposer associated with this container. Instances can be associated