Как перехватчик Unity может определить, исходит ли вызов из WCF или из внутренней службы?

У меня есть служба WCF, подключенная к перехватчику Unity, и все вызовы уровня WCF перехватываются Unity для целей аудита. Однако Unity, похоже, перехватывает ВСЕ вызовы для разрешения интерфейса, независимо от того, исходит ли вызов из WCF или внутри.

Рассмотрим следующий код:

[ServiceContract]
public interface IMyUtilityService
{
    [OperationContract]
    void DoUtilityStuff();
}

[ServiceContract]
public interface IMyService
{
    [OperationContract]
    void DoStuff();
}

class MyService : IMyService
{
    public MyService(IMyUtilityService myUtilityService)
    {
    }

    public void DoStuff()
    {
    }
}

Сервисные интерфейсы регистрируются в Unity с перехватом:

container.RegisterType<IMyUtilityService, MyUtilityService>(
    new Interceptor<InterfaceInterceptor>(), 
    new InterceptionBehavior<PipelineInterceptor>());

container.RegisterType<IMyService, MyService>(
    new Interceptor<InterfaceInterceptor>(), 
    new InterceptionBehavior<PipelineInterceptor>());

Когда вызов WCF выполняется в IMyService, я получаю срабатывание перехватчика, что здорово, и я могу провести некоторый аудит. Однако при разрешении IMyService перехватчик снова срабатывает, поскольку IMyUtilityService внедряется в конструктор IMyService.

Есть ли способ настроить Unity, чтобы предотвратить это? Или внутри перехватчика есть способ определить, что перехват был непосредственно запущен WCF? Или мне нужно создать другой слой интерфейса для разделения внешних и внутренних вызовов?


person Hawk    schedule 26.05.2016    source источник
comment
Почему вы используете сервис-интерфейс внутри? Проблема должна решиться сама собой путем перемещения вашей логики из сервисного интерфейса в более подходящий класс (менеджер, репозиторий и т. д.). Затем вы можете вместо этого разрешить этот класс/интерфейс. Сервисный уровень должен быть максимально тупым.   -  person smoksnes    schedule 27.05.2016
comment
Наша архитектура разделена на уровень репозитория и уровень обслуживания. Услуги могут потребляться другими службами. Некоторые сервисы доступны через WCF.   -  person Hawk    schedule 27.05.2016
comment
Я понимаю. Тогда вы сможете использовать мой ответ ниже.   -  person smoksnes    schedule 27.05.2016
comment
Если я правильно понимаю ваше предложение, то я должен ввести уровень бизнес-логики между уровнем обслуживания и уровнем данных, где находится вся бизнес-логика. Я считаю, что мы решили не делать этого, поскольку в большинстве случаев это будет прямое сопоставление службы WCF со слоем бизнес-логики. Кроме того, в приложении мало бизнес-логики, поэтому тупой сервис, тупая бизнес-логика, некоторая логика постоянства. Слой казался излишним.   -  person Hawk    schedule 27.05.2016
comment
Я полностью понимаю вашу точку зрения. Мое предложение имеет смысл только в том случае, если в ваших сервисах много логики.   -  person smoksnes    schedule 27.05.2016


Ответы (2)


Мне удалось решить вопрос с креативной регистрацией сервисов в Unity. Ранее служба была зарегистрирована в Unity либо как внутренняя служба, либо как служба WCF с перехватом. Если служба WCF используется внутри, возникают проблемы с перехватчиком.

Примечание: проблема с перехватчиком могла быть связана с тем, что мы использовали ленивое разрешение зависимостей.

Проблему можно решить, зарегистрировав все службы в Unity для внутреннего разрешения, а затем зарегистрировав службы WCF с явными именами. Когда конечная точка WCF активирована, экземпляр может быть разрешен с использованием явного имени.

Например, регистрация сервиса:

container.RegisterType(interfaceType, implementationType);

if (isWCF)
    container.RegisterType(
        interfaceType, 
        implementationType, 
        "WCF", // name for resolving WCF services
        new Interceptor<InterfaceInterceptor>(), 
        new InterceptionBehaviour<PipelineInterceptor>());

А затем создайте экземпляр в Instance Provider:

public object GetInstance(InstanceContext instanceContext, Message message)
{
    return _container.Resolve(_interfaceType, "WCF");
}

Решение является предпочтительным, так как перехватчик теперь регистрируется и активируется только против вызова служб WCF.

person Hawk    schedule 30.05.2016

Самый простой способ — проверить, есть ли у вас Контекст операции.

if (OperationContext.Current != null)
{
    // Called through WCF.
}
else
{
    // Not WCF.
}

И в перехватчике.

public class PipelineInterceptor : IInterceptionBehavior
{
    public bool WillExecute
    {
        get { return OperationContext.Current != null; }
    }

    // Other ...

}
person smoksnes    schedule 27.05.2016