开发者

Context and parameter-specific injection down a Ninject 2 dependency graph

I am interested in creating an instance of an object that implements my IDistributor interface using IoC and Ninject.

I have created a concerete implementation (Distributor), and all dependent objects/interfaces as required.

The Distributor requires a constructor-injected dependency of type IDistributorContext. The concrete type DistributorContext can only be created by passing in parameters at runtime.

I'm struggling to decide the best way of implementing this, and also the best way of encapsulating this for exposure to the rest of my application. At present, I have decided to create a Factory, which is responsible for creating a Ninject Kernel, and resolving dependencies in the Create method. So, my questions are:

  1. Is this the preferred solution? Or would it be better to create a Module that is then exposed to my other assemblies and allow them to instantiate the object?
  2. What is the preferred way to cr开发者_开发问答eate my Distributor at runtime? Noting the runtime parameters that need to be provided to the DistributorContext object further down the dependency graph.

The code is:

public class DistributorFactory : IDistributorFactory
{
    private const string ContextIdKey = "contextIdKey";
    private readonly IKernel _kernel;

    public DistributorFactory()
    {
        _kernel = CreateKernel();
    }

    public IDistributor Create(int queueId)
    {
        return _kernel.Get<IDistributor>(new Parameter(ContextIdKey, queueId, true));
    }

    private IKernel CreateKernel()
    {
        var kernel = new StandardKernel();

        kernel.Bind<IDistributorContext>().To<DistributorContext>().WithConstructorArgument("contextId",
            (context, target) => context.Parameters.First(x => x.Name == QueueIdKey).GetValue(context, target));

        kernel.Bind<IReceiveQueue>().To<ReceiveQueue>();
        kernel.Bind<IDistributor>().To<Distributor>();

        return kernel;
    }
}

public class Distributor : IDistributor
{
    private readonly IReceiveQueue _receiveQueue;
    private readonly IDistributorContext _distributorContext;

    public Distributor(IReceiveQueue receiveQueue, IDistributorContext distributorContext)
    {
        _receiveQueue = receiveQueue;
        _distributorContext = distributorContext;
    }
}

public class DistributorContext: IDistributorContext
{
    private readonly int _contextId;

    public DistributorContext(int contextId)
    {
        _contextId = contextId;
    }
}

Edit:

My application is creating several distributors based on configuration settings stored in XML. I don't wish to couple my service-based configuration with my distributor implementation, and that is why I went down the route of creating a factory.

An alternative could be to create a IDistributorConfiguration and get Ninject to automatically provide a list of Distributors to my consuming service. But then again, I'm not sure that this is any better?


Is is working? Yes defenately.

Is it the prefered solution? Probably not. It's a complicated solution which is normally a hint that there is something wrong in the implementation. But to answer this question you must give information what's the goal behind your implementation. And by goal I do not mean what you want Ninject to do, but rather what your application should do.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜