在 .NET RESTful 应用程序中使用 Ninject?
我是 RESTful 服务的新手,有一段时间没有使用 IoC 重新连接堆栈了,所以这给了我一个轻微的打击。
我有一个看起来像这样的 WCF 服务(简化版):
public interface IESIID
{
[OperationContract]
[WebGet(UriTemplate = "/{guid}/{id}", ResponseFormat = WebMessageFormat.Json,
BodyStyle = WebMessageBodyStyle.Wrapped)]
Message LookupESIID(string guid, string id);
}
public class ESIID : BaseREST<ESI>, IESIID
{
private readonly ITXESIIDService _bllSvc;
public ESIID(ITXESIIDService svc)
{
_bllSvc = svc;
}
public Message LookupESIID(string guid, string id)
{
return GetById(guid, id);
}
private Message GetById(string guid, string id)
{
apiAuthentication = new APIKeyAuthentication();
if (!apiAuthentication.IsValidAPIKey(guid))
return APIError();
//_bllSvc = new TXESIIDService(); <--- WANTING TO AVOID THIS!!!!
var results = _bllSvc.SelectByID(id);
return results.Count == 0 ? NoResults() : CreateMessage(results);
}
}
很好,这非常简单。我确实添加了一个构造函数参数,因为调用了 BLL TXESIIDService 方法。
所以现在,我已经更改了 Ninject 的全局文件,现在看起来像这样:
public class Global : NinjectWcfApplication
{
protected override void Application_Start(object sender, EventArgs e)
{
RegisterRoutes();
}
protected override IKernel CreateKernel()
{
return new StandardKernel(new RestServiceModel());
}
private static void RegisterRoutes()
{
RouteTable.Routes.Add(new ServiceRoute("ESIID", new NinjectServiceHostFactory(), typeof(ESIID)));
}
}
并且还添加了我的模块:
public class RestServiceModel : NinjectModule
{
public override void Load()
{
Bind<ITXESIIDService>().To<TXESIIDService>();
Bind<IDoNotSolicitService>().To<DoNotSolicitService>();
}
}
并且为了进行故障排除,我通过自己的 NinjectServiceHostFactory 添加了
public class NinjectServiceHostFactory : WebServiceHostFactory
{
protected override ServiceHost CreateServiceHost(Type serviceType, Uri[] baseAddresses)
{
var serviceTypeParameter = new ConstructorArgument("serviceType", serviceType);
var baseAddressesParameter = new ConstructorArgument("baseAddresses", baseAddresses);
return KernelContainer.Kernel.Get<NinjectServiceHost>(serviceTypeParameter, baseAddressesParameter);
}
}
当我运行此文件时,我收到一条错误,该行:
return KernelContainer.Kernel.Get<NinjectServiceHost>(serviceTypeParameter, baseAddressesParameter);
不能为空。
显然我在这里遗漏了一些东西,但我不知道是什么。此时我已经尝试了各种方法,我看到的大多数示例都是针对 WCF 服务的,而我设法找到的 RESTful 示例对于那些熟悉的 w/Ninject 或 IoC 常规程序来说有点太适合了。
另外,在我的业务和数据层(使用实体框架)中,我也希望在那里实现 Ninject,最佳实践是将各层单独连接还是可以在一个地方完成所有操作?
谢谢。
更新1 我已经纠正了绑定问题,但这仍然让我很沮丧。我正在使用 Ninject.Extensions.Wcf,它正在轰炸寻找 NinjectWcfApplication.cs 文件,这似乎根本不正确。我使用 NuGet 包含 Ninject 的包,这可能是版本问题吗?
I'm new to RESTful services and haven't had to freshly wire up a stack using IoC in a while, so this is giving me a mild stroke.
I have a WCF service that looks like this (simplified):
public interface IESIID
{
[OperationContract]
[WebGet(UriTemplate = "/{guid}/{id}", ResponseFormat = WebMessageFormat.Json,
BodyStyle = WebMessageBodyStyle.Wrapped)]
Message LookupESIID(string guid, string id);
}
public class ESIID : BaseREST<ESI>, IESIID
{
private readonly ITXESIIDService _bllSvc;
public ESIID(ITXESIIDService svc)
{
_bllSvc = svc;
}
public Message LookupESIID(string guid, string id)
{
return GetById(guid, id);
}
private Message GetById(string guid, string id)
{
apiAuthentication = new APIKeyAuthentication();
if (!apiAuthentication.IsValidAPIKey(guid))
return APIError();
//_bllSvc = new TXESIIDService(); <--- WANTING TO AVOID THIS!!!!
var results = _bllSvc.SelectByID(id);
return results.Count == 0 ? NoResults() : CreateMessage(results);
}
}
Fine, that's pretty straight forward. I did add a constructor parameter because with the call to the BLL TXESIIDService method.
So now, I've altered my Global file for Ninject which now looks something like this:
public class Global : NinjectWcfApplication
{
protected override void Application_Start(object sender, EventArgs e)
{
RegisterRoutes();
}
protected override IKernel CreateKernel()
{
return new StandardKernel(new RestServiceModel());
}
private static void RegisterRoutes()
{
RouteTable.Routes.Add(new ServiceRoute("ESIID", new NinjectServiceHostFactory(), typeof(ESIID)));
}
}
and also added my module:
public class RestServiceModel : NinjectModule
{
public override void Load()
{
Bind<ITXESIIDService>().To<TXESIIDService>();
Bind<IDoNotSolicitService>().To<DoNotSolicitService>();
}
}
And for troubleshooting I added by own NinjectServiceHostFactory
public class NinjectServiceHostFactory : WebServiceHostFactory
{
protected override ServiceHost CreateServiceHost(Type serviceType, Uri[] baseAddresses)
{
var serviceTypeParameter = new ConstructorArgument("serviceType", serviceType);
var baseAddressesParameter = new ConstructorArgument("baseAddresses", baseAddresses);
return KernelContainer.Kernel.Get<NinjectServiceHost>(serviceTypeParameter, baseAddressesParameter);
}
}
When I run this as in I get an error that the line:
return KernelContainer.Kernel.Get<NinjectServiceHost>(serviceTypeParameter, baseAddressesParameter);
cannot be null.
Obviously I'm missing something here, but I can't figure out what. I've tried various things at this point and most examples I see are for WCF services and the RESTful ones I've manage to find are just a bit too geared for those familiar w/Ninject or IoC regulars.
Also, In my Business and Data layers (using entity framework), I'm looking to implement Ninject there as well, is it best practice to have the layers wired up separately or is it possible to do it all in one spot?
Thanks.
UPDATE 1
I have corrected the binding issue, but this still bombs on me. I'm using Ninject.Extensions.Wcf and it's bombing looking for NinjectWcfApplication.cs file which doesn't seem right at all. I used NuGet to include a package for Ninject, could this be a version issue?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
这可能是一个拼写错误,但是您的意思是在模块中将接口绑定到自身吗?通常,您将接口绑定到具体类型。如果 Ninject 尝试实例化接口类型,它肯定会失败,并且根据 Ninject 设置的特定错误处理行为,它会抛出或返回 null。因此,请确保模块配置为查找真正的类:
This may be a typo, but are you meaning to bind interfaces to themselves in your module? Usually you bind an interface to a concrete type. If Ninject tries to instantiate an interface type, it will definitely fail, and depending on specific error-handling behavior of your Ninject setup it'll either throw out or return null. So, make sure the module is configured to look for a real class:
重写虚拟方法时,您始终必须调用基方法。请参阅
Application_Start()
。You always have to call the base method when overriding a virtual method. See
Application_Start()
.关于您的更新:我是 ninject 的新手,所以我对旧版本一无所知,但我想您尝试一下 示例 Ninject 扩展 首先。如果他们跑了,你就知道一定是别的什么。
Regarding your update: I am new to ninject so I don't know anything about older versions but I suppose you try out the Example Ninject Extensions first. If they run, you know it must be something else.