使用SimpleInjector混合WebAPI和WCF

时间:2016-02-10 14:50:49

标签: wcf asp.net-web-api simple-injector

我创建了一个使用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生活方式的注射,我试图"只需添加" 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生活方式,并在尝试调用方法时抛出错误:

  

ITransferOrderRequest已注册为' Web API请求'生活方式,但实例是在Web API请求的上下文之外请求的。

更新

我试图创建一个具有不同生活方式的第二个容器:

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注册为WCF运营生活方式。

我已经看到有混合生活方式,但我不知道如何检测它目前是否是WCF或WebApi请求......

谢谢!

1 个答案:

答案 0 :(得分:3)

  

我不知道如何检测它当前是否是WCF或WebApi请求......

您可以通过检查OperationContext.Current != null

来检查请求是否是WCF请求
var lifestyle = Lifestyle.CreateHybrid(
    lifestyleSelector: () => OperationContext.Current != null,
    trueLifestyle: new WcfOperationLifestyle(true),
    falseLifestyle: new WebApiRequestLifestyle()
);
  

我不知道通过新手控制器而失去的东西"

要在评论中澄清我的建议,我了解你的来源。我仍然认为你应该考虑在完全排除之前通过HTTP做这件事。你可以克服" hardwire路线"将URL作为WCF项目的app.config的一部分。有一些不错的配置转换工具,您可以使用它来为不同的环境生成不同的路由。更改配置以修改程序行为是松散耦合的,并且具有高度凝聚力。

效率稍差,但我认为如果实际额外延迟足够小,成本可能是合理的。您丢失的内容是添加到控制器的所有WebAPI请求管道优势,例如内容协商,过滤器等。由于您没有发布任何代码并且您的决定正常,我认为您确实是只有GetResults(string data)方法体具有其作用域依赖性,并且不需要任何其他内容。

但请注意,您的决定会在WCF服务和WebAPI控制器之间创建比HTTP网络调用更紧密的耦合。