Reputation: 3185
My Class Structure is:
public class PhotoService {
private IRepository _repo;
private DTConfig _config;
public PhotoService(IRepository repo, DTConfig config)
{
_repo = repo;
_config = config;
}
}
public class DTConfig
{
private int _accountId;
public DTConfig(int accountId)
{
_accountId = accountId;
}
}
My Ninject Bindings are like:
var kernel = new StandardKernel();
kernel.Bind<IPhotoService>().To<PhotoService>();
kernel.Bind<IRepository>().To<Repository>();
kernel.Bind<DTConfig>().ToSelf();
Now what I want, is to pass the accountId
as a parameter while creating an instance of PhotoService
var photo = kernel.Get<IPhotoService>();
How can I pass the parameter to DTConfig while creating an instance of PhotoService. The accountId is fetched from a service and is not available in compile time.
Feel free to comment if any other information is required.
Upvotes: 3
Views: 2174
Reputation: 4021
While I have found that it is overkill in some situations, using a factory will help provide constructor-like features while preserving the style of writing for injection. This is provided by the Ninject.Extensions.Factory
extension.
At a basic level, you create a factory interface which has a matching subset of the constructor arguments. It can both resolve bound components, and require input itself. Here is a slightly modified example from the wiki;
public class Foo
{
readonly IBarFactory barFactory;
public Foo(IBarFactory barFactory)
{
this.barFactory = barFactory;
}
public void Do()
{
var bar = this.barFactory.CreateBar("doodad");
//Do Foo things
bar.Stuff();
}
}
public interface IBarFactory
{
IBar CreateBar(string someParameter);
}
public interface IBar
{
void Stuff();
}
public class Bar : IBar
{
public Bar(IDependancy aDependancy, string someParameter)
{
//Initialise Object
}
public void Stuff()
{
//Do Stuff
}
}
Then by binding a factory with;
_kernel.Bind<IBarFactory>().ToFactory();
the extension will do some magic behind the scenes.
In this example, assuming IDependancy
is bound correctly, calling the CreateBar
method of the factory will resolve any dependancies in parallel with inserting your parameter.
One word of caution, however, is that the parameter names need to be the same.
Upvotes: 4
Reputation: 5437
Yannick's answer is a good, however, here's an alternative: create an IAccountService
that has the logic to find and return the AccountId. Then inject that service into your IPhotoService
.
Upvotes: 3
Reputation: 5910
There's the concept of a ConstructorArgument
in Ninject, which allows you to pass through variables only known at runtime. The typical example of this would be:
var photoService = kernel.Get<IPhotoService>(new ConstructorArgument("accountId", <your value here>));
Now the caveat with this is that this only goes one level deep. There is however a contructor that accepts a bool flag called shouldInherit
, which allows your values to propagate to the children when resolving the concrete types:
var photoService = kernel.Get<IPhotoService>(new ConstructorArgument("accountId", <your value here>, shouldInherit:true));
Upvotes: 7