How to pass parameters down the dependency chain using Ninject

空扰寡人 提交于 2019-12-10 11:26:57

问题


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.


回答1:


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.




回答2:


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));



回答3:


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.



来源:https://stackoverflow.com/questions/28745332/how-to-pass-parameters-down-the-dependency-chain-using-ninject

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!