问题
I'm using a factory to return a datasender:
Bind<IDataSenderFactory>()
.ToFactory();
public interface IDataSenderFactory
{
IDataSender CreateDataSender(Connection connection);
}
I have two different implementations of datasender (WCF and remoting) which take different types:
public abstract class Connection
{
public string ServerName { get; set; }
}
public class WcfConnection : Connection
{
// specificProperties etc.
}
public class RemotingConnection : Connection
{
// specificProperties etc.
}
I am trying to use Ninject to bind these specific types of datasender based on the type of Connection passed from the parameter. I have tried the following unsuccessfully:
Bind<IDataSender>()
.To<RemotingDataSender>()
.When(a => a.Parameters.Single(b => b.Name == "connection") as RemotingConnection != null)
I believe this is because '.When' only provides a request and I would need the full context to be able to retrieve the actual parameter value and check its type. I'm at a loss as to what to do, other than using named bindings, actually implementing the factory and putting the logic in there i.e.
public IDataSender CreateDataSender(Connection connection)
{
if (connection.GetType() == typeof(WcfConnection))
{
return resolutionRoot.Get<IDataSender>("wcfdatasender", new ConstructorArgument("connection", connection));
}
return resolutionRoot.Get<IDataSender>("remotingdatasender", new ConstructorArgument("connection", connection));
}
回答1:
After some looking into Ninject source I have found following:
a.Parameters.Single(b => b.Name == "connection")gives you variable of typeIParameter, not real parameter.IParameterhas methodobject GetValue(IContext context, ITarget target)that requires not null context parameter (target can be null).I have not found any way to get IContext from Request (variable a in your sample).
Contextclass does not have parameterless constructor so we can't create new Context.
To make it work you can create dummy IContext implementation like:
public class DummyContext : IContext
{
public IKernel Kernel { get; private set; }
public IRequest Request { get; private set; }
public IBinding Binding { get; private set; }
public IPlan Plan { get; set; }
public ICollection<IParameter> Parameters { get; private set; }
public Type[] GenericArguments { get; private set; }
public bool HasInferredGenericArguments { get; private set; }
public IProvider GetProvider() { return null; }
public object GetScope() { return null; }
public object Resolve() { return null; }
}
and than use it
kernel.Bind<IDataSender>()
.To<RemotingDataSender>()
.When( a => a.Parameters
.Single( b => b.Name == "connection" )
.GetValue( new DummyContext(), a.Target )
as RemotingConnection != null );
It would be nice if someone could post some info about obtaining Context from inside When()...
来源:https://stackoverflow.com/questions/15267368/ninject-conditional-binding-based-on-parameter-type