You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
In my application, I'm using a custom attribute to provide info to Windsor that it can use to generate named registrations for different implementations of the same underlying service type.
The issue is that if a scenario is encountered where the same name would be used to register multiple components, then it creates a race condition, where the first type that Windsor discovers and registers will get added to the container, while the other types that try to register with the same name, simply do not get added to the container. No exception is triggered, which is the behavior I expected.
Unfortunately, I can't share the exact code, but here is some similar code that should reproduce the same issue. Whichever type is discovered by Windsor first , either ServiceImplementation1 or ServiceImplementation2, will get registered, while the attempt to register the 2nd component with the same name will fail silently.
namespace MyApp
{
[AttributeUsage(AttributeTargets.Class)]
public class CustomAttribute : Attribute
{
public string Key { get; }
public CustomAttribute(string key)
{
Key = key;
}
}
// the service type registered with the container
public interface IServiceInterface { }
// implementation #1
[Custom("implementation1")]
public class ServiceImplementation1 : IServiceInterface { }
// implementation #2: this uses the same key as #1, to trigger a registration failure
[Custom("implementation1")]
public class ServiceImplementation2 : IServiceInterface { }
public class WindsorInstaller : IWindsorInstaller
{
public void Install(IWindsorContainer container, IConfigurationStore store)
{
container.Register(
Classes.FromAssemblyContaining<WindsorInstaller>()
.Where(t => typeof(IServiceInterface).IsAssignableFrom(t) &&
Component.HasAttribute<CustomAttribute>(t))
.Configure(reg =>
{
var attribute =
(CustomAttribute)Attribute.GetCustomAttribute(c.Implementation, typeof(CustomAttribute));
reg.Named($"{typeof(IServiceInterface).FullName}_{attribute.Key}");
})
);
}
}
public class Program
{
public static int Main(string[] args)
{
var container = new WindsorContainer().Install(FromAssembly.Containing<Program>());
// resolves to whichever component happened to be discovered first
var service = container.Resolve<IServiceInterface>($"{typeof(IServiceInterface).FullName}_implementation1");
Console.WriteLine($"Resolved {service.GetType().Name}");
// returns a single component (whichever one was successfully registered)
var allServices = container.ResolveAll<IServiceInterface>();
Console.WriteLine($"Discovered {allServices.Length} services that implement IServiceInterface");
return 0;
}
}
}
The text was updated successfully, but these errors were encountered:
FWIW... I discovered a way to deal with this issue by using the IKernel.HasComponent method to explicitly check for a duplicate named component. This still feels like something that Windsor should do by default though.
From the sample code I included earlier, here's how I changed the registration to throw an exception
container.Register(
Classes.FromAssemblyContaining<WindsorInstaller>()
.Where(t => typeof(IServiceInterface).IsAssignableFrom(t) && Component.HasAttribute<CustomAttribute>(t))
.Configure(reg =>
{
var attribute = (CustomAttribute)Attribute.GetCustomAttribute(c.Implementation, typeof(CustomAttribute));
var componentName = $"{typeof(IServiceInterface).FullName}_{attribute.Key}";
// throw an exception when trying to register another component with same name
if (container.Kernel.HasComponent(componentName))
throw new ComponentRegistrationException("some useful message about registration failure");
reg.Named(componentName);
})
);
In my application, I'm using a custom attribute to provide info to Windsor that it can use to generate named registrations for different implementations of the same underlying service type.
The issue is that if a scenario is encountered where the same name would be used to register multiple components, then it creates a race condition, where the first type that Windsor discovers and registers will get added to the container, while the other types that try to register with the same name, simply do not get added to the container. No exception is triggered, which is the behavior I expected.
Unfortunately, I can't share the exact code, but here is some similar code that should reproduce the same issue. Whichever type is discovered by Windsor first , either ServiceImplementation1 or ServiceImplementation2, will get registered, while the attempt to register the 2nd component with the same name will fail silently.
The text was updated successfully, but these errors were encountered: