Альтернатива HttpContext при использовании NInject со службой WCF, размещенной в WAS с использованием привязки MSMQ
У меня есть односторонняя служба WCF с использованием привязки MSMQ, которая активируется с помощью службы активации Windows в IIS 7.0.
Я большой поклонник NInject, поэтому я использую расширение NInject для WCF, которое отлично подойдет для типичного HTTP-сервиса WCF.
Однако в службах активации WAS нет конвейера HTTP, поэтому я не могу использовать InRequestScope при связывании моих типов, потому что System.Web.HttpContext.Current имеет значение null. Я изо всех сил пытаюсь найти альтернативу при использовании WAS, которая даст мне то, что я хочу. Атрибут режима AspCompatibility также не работает в этом режиме.
Я думал, что InThreadScope может работать, но служба создается в отдельном потоке, чем то, в котором она выполняется.
Так что в основном мне нужен эквивалент HttpContext для WCF+WAS, чтобы охватить мои объекты на уровне запроса. Есть ли в этом мире какой-то статический объект, который работал бы так же, или у кого-то есть идеи о том, что я могу взломать вместе?
2 ответа
Я реализовал свои собственные расширения WCF для Ninject 2.0, прежде чем я понял, что это было на github. Моя реализация немного отличается, но я нашел решение для определения объема объектов:
using System;
using Ninject.Activation;
namespace Ninject.Contrib.Wcf {
/// <summary>
/// Defines Scope Callbacks for WCF Context.
/// </summary>
public class NinjectWcfScopeCallbacks {
/// <summary>
/// Defines WCF Context scope.
/// </summary>
public static readonly Func<IContext, object> WcfContext =
ctx => (System.ServiceModel.OperationContext.Current != null
? System.ServiceModel.OperationContext.Current.
InstanceContext.
Extensions.Find<NinjectInstanceContext>()
: null);
/// <summary>
/// Defines WCF Web Context scope.
/// </summary>
public static readonly Func<IContext, object> WcfWebContext =
ctx => System.ServiceModel.Web.WebOperationContext.Current;
}
}
Для полноты, вот как я использую обратный вызов, определенный выше:
Bind<IHelloWorldService>()
.To<HelloWorldService>()
.InScope(NinjectWcfScopeCallbacks.WcfWebContext);
Они не размещали службы WCF в WAS, поэтому не уверены, что вы используете WcfWebContext
или же WcfContext
определено выше, но вы можете попробовать их и посмотреть. Если WebOperationContext
работает, значит, все готово. В противном случае я обнаружил, что все немного сложнее. Вы заметите, что фрагмент кода выше использует NinjectInstanceContext
класс, который прикреплен к OperationContext
, Это класс, который я написал, который использует механизм "кэширования и сбора" в Ninject 2.0, который позволяет детерминистически удалять объекты. В основном, класс реализует IExtension<InstanceContext>
которая представляет собой конструкцию WCF для прикрепления почти всего к OperationContext
, Этот класс также реализует Ninject's INotifyWhenDisposed
интерфейс, который обеспечивает поддержку для детерминированного удаления. Вот как выглядит определение класса:
/// <summary>
/// Defines a custom WCF InstanceContext extension that resolves service instances
/// using Ninject.
/// <remarks>
/// The custom InstanceContext extension provides support for deterministic disposal
/// of injected dependencies and service instances themselves by being hook into
/// Ninject's "cache and collect" mechanism (new in Ninject 2.0) for object life cycle
/// management. This allows binding object instances to the lifetime of a WCF context
/// and having them deterministically deactivated and disposed.
/// </remarks>
/// </summary>
public class NinjectInstanceContext :
IExtension<InstanceContext>, INotifyWhenDisposed {
}
Остальная часть моего расширения WCF для Ninject такая же, как и на github. Что в основном происходит, так это то, что создается поставщик экземпляров, который подключен к цепочке "активации" WCF - я не использую их конкретную терминологию, просто как я понимаю вещи. Итак, идея заключается в том, что ваш поставщик экземпляров должен предоставлять экземпляры запрашиваемого класса обслуживания WCF. Итак, вот где мы используем Ninject для создания экземпляра сервиса. Таким образом, мы также можем активировать и вводить любые зависимости. В моей реализации провайдер экземпляров заключает в себе ядро Ninject, если NinjectInstanceContext
и прикрепить его к OperationContext
, Создание службы затем делегируется этому расширению WCF. Когда поставщику экземпляра предлагается освободить службу, NinjectInstanceContext
который был прикреплен к OperationContext, который в порядке реализации INotifyWhenDisposed
вызывает детерминированное удаление службы (и, возможно, ее зависимости).
Надеюсь, это обсуждение поможет. Я посмотрю, смогу ли я разместить здесь более конкретный код, если вам интересно.