使用 SimpleInjector 混合 WebAPI 和 WCF
Mix WebAPI and WCF with SimpleInjector
我创建了一个使用 SimpleInjector 的 WebApi 应用程序。
现在 API 的用户希望 WCF 端点使用它(无论出于何种原因)。
为了让事情对我来说更简单,我只想从 WCF 服务内部调用 WebApi 控制器:
public class MyService : IMyService
{
private MyApiController controller;
public MyService(IMyInjection inject)
{
controller = new MyApiController(inject);
}
public int GetResult(string data)
{
return controller.GetResult(data);
}
}
为了让它在 WebApi 中工作,我的控制器目前使用具有 WebApiRequestLifeStyle
生活方式的注入,我已经尝试 "just add" SimpleInjector WCF Integration :
public static void LoadDependencyInjection()
{
var container = new Container();
container.Options.DefaultScopedLifestyle = new WebApiRequestLifestyle();
container.RegisterWebApiControllers(GlobalConfiguration.Configuration);
// some more registration
// configure WCF to use SimpleInjector
container.RegisterWcfServices(Assembly.GetExecutingAssembly());
// verify
container.Verify();
// configure the global WebApi to use SimpleInjector
GlobalConfiguration.Configuration.DependencyResolver = new SimpleInjectorWebApiDependencyResolver(container);
// configure WCF to use SimpleInjector
SimpleInjectorServiceHostFactory.SetContainer(container);
}
显然,WCF 服务不喜欢 WebApi 的生活方式,并且在我尝试调用方法时抛出错误:
The ITransferOrderRequest is registered as 'Web API Request' lifestyle, but the instance is requested outside the context of a Web API Request.
更新
我尝试创建第二个具有不同生活方式的容器:
public static void LoadDependencyInjection()
{
// WebApi container
var webApiContainer = CreateContainer(new WebApiRequestLifestyle(true));
webApiContainer.RegisterWebApiControllers(GlobalConfiguration.Configuration);
webApiContainer.EnableHttpRequestMessageTracking(GlobalConfiguration.Configuration);
// WCF container
var wcfContainer = CreateContainer(new WcfOperationLifestyle(true));
wcfContainer.RegisterWcfServices(Assembly.GetExecutingAssembly());
// verify
webApiContainer.Verify();
wcfContainer.Verify();
// configure the global WebApi to use SimpleInjector
GlobalConfiguration.Configuration.DependencyResolver = new SimpleInjectorWebApiDependencyResolver(webApiContainer);
// configure WCF to use SimpleInjector
SimpleInjectorServiceHostFactory.SetContainer(wcfContainer);
}
private static Container CreateContainer(ScopedLifestyle lifestyle)
{
var container = new Container();
// set the default lifestyle
container.Options.DefaultScopedLifestyle = lifestyle;
// here I register a bunch of interfaces/instances using the Scoped lifestyle
return container;
}
但是对 container.Options.DefaultScopedLifestyle = lifestyle;
的第二次调用(使用 WcfOperationLifestyle
)也改变了第一个容器的默认生活方式!在这种情况下,当我调用我的 WebApi 服务时,我得到了同样的错误,但相反:
IMyStuff is registered as WCF operation lifestyle.
我看到有一种混合生活方式,但我不知道如何检测它当前是 WCF 还是 WebApi 请求...
谢谢!
I have no idea how to detect whether it's currently a WCF or WebApi request...
您可以通过检查是否OperationContext.Current != null
.
来检查请求是否为WCF请求
var lifestyle = Lifestyle.CreateHybrid(
lifestyleSelector: () => OperationContext.Current != null,
trueLifestyle: new WcfOperationLifestyle(true),
falseLifestyle: new WebApiRequestLifestyle()
);
I don't know "what I lose by just newing up a controller".
为了澄清我在评论中的建议,我知道你来自哪里。我仍然认为,在完全排除它之前,您应该考虑通过 HTTP 执行此操作。您可以通过使 WCF 项目的 app.config 的 URL 部分克服 "hardwire routes" 问题。您可以使用一些不错的配置转换工具为不同的环境生成不同的路由。更改配置以修改程序行为是松散耦合的,并且是高度内聚的。
它 效率有点低,但我认为如果 实际 额外延迟足够小,成本可能是合理的。您失去的是添加到控制器的所有 WebAPI 请求管道优势,例如内容协商、过滤器等。由于您没有 post 任何这些代码并且对您的决定没问题,我假设您实际上仅在 GetResults(string data)
方法主体及其作用域依赖项之后,不需要任何其他内容。
但是请注意,与 HTTP 网络调用相比,您的决定会在 WCF 服务和 WebAPI 控制器之间建立更紧密的耦合。
我创建了一个使用 SimpleInjector 的 WebApi 应用程序。
现在 API 的用户希望 WCF 端点使用它(无论出于何种原因)。
为了让事情对我来说更简单,我只想从 WCF 服务内部调用 WebApi 控制器:
public class MyService : IMyService
{
private MyApiController controller;
public MyService(IMyInjection inject)
{
controller = new MyApiController(inject);
}
public int GetResult(string data)
{
return controller.GetResult(data);
}
}
为了让它在 WebApi 中工作,我的控制器目前使用具有 WebApiRequestLifeStyle
生活方式的注入,我已经尝试 "just add" SimpleInjector WCF Integration :
public static void LoadDependencyInjection()
{
var container = new Container();
container.Options.DefaultScopedLifestyle = new WebApiRequestLifestyle();
container.RegisterWebApiControllers(GlobalConfiguration.Configuration);
// some more registration
// configure WCF to use SimpleInjector
container.RegisterWcfServices(Assembly.GetExecutingAssembly());
// verify
container.Verify();
// configure the global WebApi to use SimpleInjector
GlobalConfiguration.Configuration.DependencyResolver = new SimpleInjectorWebApiDependencyResolver(container);
// configure WCF to use SimpleInjector
SimpleInjectorServiceHostFactory.SetContainer(container);
}
显然,WCF 服务不喜欢 WebApi 的生活方式,并且在我尝试调用方法时抛出错误:
The ITransferOrderRequest is registered as 'Web API Request' lifestyle, but the instance is requested outside the context of a Web API Request.
更新
我尝试创建第二个具有不同生活方式的容器:
public static void LoadDependencyInjection()
{
// WebApi container
var webApiContainer = CreateContainer(new WebApiRequestLifestyle(true));
webApiContainer.RegisterWebApiControllers(GlobalConfiguration.Configuration);
webApiContainer.EnableHttpRequestMessageTracking(GlobalConfiguration.Configuration);
// WCF container
var wcfContainer = CreateContainer(new WcfOperationLifestyle(true));
wcfContainer.RegisterWcfServices(Assembly.GetExecutingAssembly());
// verify
webApiContainer.Verify();
wcfContainer.Verify();
// configure the global WebApi to use SimpleInjector
GlobalConfiguration.Configuration.DependencyResolver = new SimpleInjectorWebApiDependencyResolver(webApiContainer);
// configure WCF to use SimpleInjector
SimpleInjectorServiceHostFactory.SetContainer(wcfContainer);
}
private static Container CreateContainer(ScopedLifestyle lifestyle)
{
var container = new Container();
// set the default lifestyle
container.Options.DefaultScopedLifestyle = lifestyle;
// here I register a bunch of interfaces/instances using the Scoped lifestyle
return container;
}
但是对 container.Options.DefaultScopedLifestyle = lifestyle;
的第二次调用(使用 WcfOperationLifestyle
)也改变了第一个容器的默认生活方式!在这种情况下,当我调用我的 WebApi 服务时,我得到了同样的错误,但相反:
IMyStuff is registered as WCF operation lifestyle.
我看到有一种混合生活方式,但我不知道如何检测它当前是 WCF 还是 WebApi 请求...
谢谢!
I have no idea how to detect whether it's currently a WCF or WebApi request...
您可以通过检查是否OperationContext.Current != null
.
var lifestyle = Lifestyle.CreateHybrid(
lifestyleSelector: () => OperationContext.Current != null,
trueLifestyle: new WcfOperationLifestyle(true),
falseLifestyle: new WebApiRequestLifestyle()
);
I don't know "what I lose by just newing up a controller".
为了澄清我在评论中的建议,我知道你来自哪里。我仍然认为,在完全排除它之前,您应该考虑通过 HTTP 执行此操作。您可以通过使 WCF 项目的 app.config 的 URL 部分克服 "hardwire routes" 问题。您可以使用一些不错的配置转换工具为不同的环境生成不同的路由。更改配置以修改程序行为是松散耦合的,并且是高度内聚的。
它 效率有点低,但我认为如果 实际 额外延迟足够小,成本可能是合理的。您失去的是添加到控制器的所有 WebAPI 请求管道优势,例如内容协商、过滤器等。由于您没有 post 任何这些代码并且对您的决定没问题,我假设您实际上仅在 GetResults(string data)
方法主体及其作用域依赖项之后,不需要任何其他内容。
但是请注意,与 HTTP 网络调用相比,您的决定会在 WCF 服务和 WebAPI 控制器之间建立更紧密的耦合。