我想使用Ninject.Wcf扩展来创建参数化服务主机实例。
例如,我有一个类MyWCFHandler
,只有以下构造函数:
public MyWCFHandler(UserManager manager)
{
_manager = manager;
}
但是当我写var myServiceHost = new ServiceHost(typeof(MyWCFHandler));
时,我无法将依赖项对象传递给构造函数。
我不想搞乱提供的自定义ServiceHost How do I pass values to the constructor on my wcf service?
我决定采用Ninject的方式,但不能完全理解如何在我的情况下采取行动。
以下是我理解Ninject中的WCF扩展工作原理:
创建一个继承Ninject模块的类,并编写如下内容:
internal class ServiceModule : NinjectModule
{
public override void Load()
{
Bind<IUserManager>().To<UserManager>().WithConstructorParameters(myUserManagerIwantToUseInWCFHandler);
}
}
将使用新ServiceModule()初始化的内核添加到KernelContainer。
像这样使用NinjectServiceHost:
var service = KernelContainer.Kernel.Get<IMyWCFHandler>();
_host = new NinjectServiceHost( service );
在那里我应该准备好我的主人才能打开。
问题是:
我应该如何将构造函数参数传递给NinjectModule?我准备好将参数绑定到它时,是否应该创建NinjectModule的实例?如何将它们传递给Get方法?
不幸的是,没有一个示例可以简单地显示参数化的ServiceHost启动。我甚至不关心它是否是我使用的Ninject。无论哪种解决方案都有一个很好的例子 - 我很好,因为我只是决定使用什么IoC容器。
答案 0 :(得分:6)
关于ninject。答案是,它取决于您是否需要单个服务或每个请求的新实例。使用单件服务,您可以执行以下操作:
public class TimeServiceModule : NinjectModule
{
/// <summary>
/// Loads the module into the kernel.
/// </summary>
public override void Load()
{
this.Bind<ITimeService>().To<TimeService>();
this.Bind<ServiceHost>().ToMethod(ctx => ctx.Kernel.Get<NinjectServiceHost>(new ConstructorArgument("singletonInstance", c => c.Kernel.Get<ITimeService>())));
}
}
internal static class Program
{
private static void Main()
{
var kernel = new StandardKernel(new TimeServiceModule());
var serviceHost = kernel.Get<ServiceHost>();
serviceHost.AddServiceEndpoint(typeof(ITimeService), new NetTcpBinding(), "net.tcp://localhost/TimeService");
try
{
serviceHost.Open();
}
finally
{
serviceHost.Close();
}
}
}
按要求方式:
public interface IServiceTypeProvider
{
/// <summary>
/// Gets the service types.
/// </summary>
/// <value>The service types.</value>
IEnumerable<Type> Types { get; }
}
Func<Type, ServiceHost> serviceHostFactory
foreach (Type serviceType in this.ServiceTypeProvider.Types)
{
// I do some magic here to query base contracts because all our service implement a marker interface. But you don't need this. But then you might need to extend the type provider interface.
IEnumerable<Type> contracts = QueryBaseContracts(serviceType );
var host = this.CreateHost(serviceType);
foreach (Type contract in contracts)
{
Binding binding = this.CreateBinding();
string address = this.CreateEndpointAddress(contract);
this.AddServiceEndpoint(host, contract, binding, address);
}
host.Description.Behaviors.Add(new ServiceFacadeBehavior());
this.OpenHost(host);
this.serviceHosts.Add(host);
}
protected virtual ServiceHost CreateHost(Type serviceType )
{
return this.serviceHostFactory(serviceType );
}
public class YourWcfModule : NinjectModule
{
/// <summary>
/// Loads the module into the kernel.
/// </summary>
public override void Load()
{
this.Bind<Func<Type, ServiceHost>>().ToMethod(
ctx =>
(serviceType) =>
ctx.Kernel.Get<NinjectServiceHost>(new ConstructorArgument("serviceType", serviceType), new ConstructorArgument("baseAddresses", new Uri[] { })));
}
}
玩得开心