Reputation: 12695
I use Castle Windsor for the DI mechanism, and I'm stuck here. I use the constructor injection type which works fine.
But, when I declare some other class's constructor, I need to invoke the default constructor, where the DI magic takes place.
So, I have the following code:
private readonly IUserService UserService = null;
public CustomAccessAttribute(IUserService userService)
{
this.UserService = userService;
}
public CustomAccessAttribute(bool someParam) : this() //here I'd like to call the above constructor
{
....
}
but I get the error
Constructor 'CustomAccessAttribute.CustomAccessAttribute(bool)' cannot call itself
I don't want to put the userService
object by myself inside of the this()
call, because the DI container should do this. So, how can I fix that error?
Upvotes: 3
Views: 860
Reputation: 956
You appear to be confused as to how IoC works. When you want to create an instance of a class there is no 'Magic' that happens to pass the parameters in, and if you new up an instance of your CustomAccessAttribute manually, Windsor will have nothing to do with it as it won't know you're creating an instance. Windsor (usually) follows the following steps:
None of these steps require any 'Magic', but they all require you to be interacting with the container itself, not just newing up instances and relying on DI Magic.
If you create a default constructor without the IUserService being passed in, you'll find that the IUserService one will be resolved anyway if you're using Resolve(), as Windsor will always resolve the constructor with the most parameters that it has registered implementations for.
The real question is why an attribute needs an IUserService in the first place, when they should only be used for metadata, not behaviour. I don't even think Windsor will happily resolve attributes without a bunch of extra setup, which hints at what a bad idea it is.
Upvotes: 3
Reputation: 149538
I think you're attacking this in the wrong way.
If you want the DI container to choose the right overload, you must provide all the arguments you want to receive. Accepting a bool
only won't help, since you actually need the IUserService
interface as well. It won't make itself appear out of nowhere. Your DI needs to know that it exists and it must be passed to appropriate constructor.
What you need is:
private readonly IUserService UserService = null;
public CustomAccessAttribute(IUserService userService)
{
this.UserService = userService;
}
public CustomAccessAttribute(IUserService userService, bool someParam) : this(userService)
{
}
Although, you usually want to make the constructor chaining outwards, from the least parameters to the most. So perhaps you'd want to do:
private readonly IUserService UserService = null;
public CustomAccessAttribute(IUserService userService) : this(userService, false)
{
}
public CustomAccessAttribute(IUserService userService, bool someParam)
{
this.UserService = userService;
}
Edit:
If the bool
you want to pass to your constructor isn't available at injection time, then constructor injection is probably not the way to go at all. Perhaps a more suitable way would be to set it as a property, which could be set once that bool
is available, or a factory pattern which will create the class instance for you when everything is available.
Upvotes: 7