When an application has a large service graph (thousands of services), instance hash collisions occur, causing the wrong implementations to be resolved at runtime.
Exception info:
ClassName: System.InvalidCastException
Message: Unable to cast object of type '{ImplentationType}' to type '{ServiceType}'.
Stack Trace:
at (Closure`6 , Scope )
at Lamar.IoC.Instances.GeneratedInstance.<>c__DisplayClass5_1.<BuildFuncResolver>b__0(Scope s)
at Lamar.IoC.Instances.GeneratedInstance.Resolve(Scope scope)
at (Closure`9 , Scope )
at Lamar.IoC.Instances.GeneratedInstance.<>c__DisplayClass5_1.<BuildFuncResolver>b__0(Scope s)
at Lamar.IoC.Instances.GeneratedInstance.Resolve(Scope scope)
at (ArrayClosure , Scope )
at Lamar.IoC.Instances.GeneratedInstance.<>c__DisplayClass5_1.<BuildFuncResolver>b__0(Scope s)
at Lamar.IoC.Instances.GeneratedInstance.Resolve(Scope scope)
at (ArrayClosure , Scope )
at Lamar.IoC.Instances.GeneratedInstance.<>c__DisplayClass5_1.<BuildFuncResolver>b__0(Scope s)
at Lamar.IoC.Instances.GeneratedInstance.Resolve(Scope scope)
at (ArrayClosure , Scope )
at Lamar.IoC.Instances.GeneratedInstance.<>c__DisplayClass5_1.<BuildFuncResolver>b__0(Scope s)
at Lamar.IoC.Instances.GeneratedInstance.Resolve(Scope scope)
at (ArrayClosure , Scope )
at Lamar.IoC.Instances.GeneratedInstance.<>c__DisplayClass5_1.<BuildFuncResolver>b__0(Scope s)
at Lamar.IoC.Instances.GeneratedInstance.Resolve(Scope scope)
at (Closure`1 , Scope )
at Lamar.IoC.Instances.GeneratedInstance.<>c__DisplayClass5_1.<BuildFuncResolver>b__0(Scope s)
at Lamar.IoC.Instances.GeneratedInstance.Resolve(Scope scope)
at (ArrayClosure , Scope )
at Lamar.IoC.Instances.GeneratedInstance.<>c__DisplayClass5_1.<BuildFuncResolver>b__0(Scope s)
at Lamar.IoC.Scope.GetInstance(Type serviceType)
at Lamar.IoC.Scope.GetInstance[T]()
I've added a workaround to recalculate the hash duplicates at startup by updating the instance names, but it would be nice if these collisions could be avoided by Lamar.
e.g. workaround
void MitigateHashCollisions(ServiceRegistry serviceRegistry)
{
var hashCollisions = serviceRegistry
.Select(x => x.ImplementationInstance)
.OfType<Instance>()
.GroupBy(x => x.Hash)
.Where(x => x.Select(y => y.ServiceType).Distinct().Count() > 1);
foreach (var collisionGroup in hashCollisions)
{
foreach (var lamarInstance in collisionGroup.Where(x => !x.IsExplicitlyNamed))
{
// Updating the name will result in a new hash
lamarInstance.Name = $"Default_{lamarInstance.ServiceType.Name}";
}
}
}
When an application has a large service graph (thousands of services), instance hash collisions occur, causing the wrong implementations to be resolved at runtime.
Exception info:
I've added a workaround to recalculate the hash duplicates at startup by updating the instance names, but it would be nice if these collisions could be avoided by Lamar.
e.g. workaround