WCF自定义行为的依赖注入

Ada*_*ger 13 c# wcf dependency-injection ninject

在我的WCF服务中,我有一个自定义消息检查器,用于将传入消息验证为XML Schema的原始XML.消息检查器具有一些依赖性(例如记录器和XML架构集合).我的问题是,我可以使用依赖注入框架(我目前正在使用Ninject)来实例化这些自定义行为并自动注入依赖项吗?

我做了一个简单的例子来展示这个概念:

using System.ServiceModel.Channels;
using System.ServiceModel.Description;
using System.ServiceModel.Dispatcher;
using Ninject.Extensions.Logging;

public class LogMessageInspector : IDispatchMessageInspector
{
    private readonly ILogger log;

    public LogMessageInspector(ILogger log)
    {
        this.log = log;
    }

    public object AfterReceiveRequest(ref Message request, IClientChannel channel, InstanceContext instanceContext)
    {
        LogMessage(ref request);
        return null;
    }

    public void BeforeSendReply(ref Message reply, object correlationState)
    {
        LogMessage(ref reply);
    }

    private void LogMessage(ref Message message)
    {
        //... copy the message and log using this.log ...
    }
}

public class LogMessageBehavior : IEndpointBehavior
{
    private readonly IDispatchMessageInspector inspector;

    public LogMessageBehavior(IDispatchMessageInspector inspector)
    {
        this.inspector = inspector;
    }

    public void AddBindingParameters(ServiceEndpoint endpoint, BindingParameterCollection bindingParameters) { }

    public void ApplyClientBehavior(ServiceEndpoint endpoint, ClientRuntime clientRuntime) { }

    public void ApplyDispatchBehavior(ServiceEndpoint endpoint, EndpointDispatcher endpointDispatcher)
    {
        endpointDispatcher.DispatchRuntime.MessageInspectors.Add(this.inspector);
    }

    public void Validate(ServiceEndpoint endpoint) { }
}
Run Code Online (Sandbox Code Playgroud)

我怎么能去注入ILoggerLogMessageInspectorLogMessageInspectorLogMessageBehavior

第二个问题,这是否过度杀伤?

编辑:如果我在代码中构建我的服务,我可以使用它,因为我使用Ninject创建行为.但是,在通过config配置服务时,我需要添加一个扩展的附加类BehaviorExtensionElement.这个类是由WCF创建的,我似乎无法找到一种方法来导致由Ninject创建它.在代码中配置:

static void Main(string[] args)
{
    using (IKernel kernel = new StandardKernel())
    {
        kernel.Bind<IEchoService>().To<EchoService>();
        kernel.Bind<LogMessageInspector>().ToSelf();
        kernel.Bind<LogMessageBehavior>().ToSelf();

        NinjectServiceHost<EchoService> host = kernel.Get<NinjectServiceHost<EchoService>>();
        ServiceEndpoint endpoint = host.AddServiceEndpoint(
            typeof(IEchoService),
            new NetNamedPipeBinding(),
            "net.pipe://localhost/EchoService"
        );
        endpoint.Behaviors.Add(kernel.Get<LogMessageBehavior>());

        host.Open();

        Console.WriteLine("Server started, press enter to exit");
        Console.ReadLine();
    }
}
Run Code Online (Sandbox Code Playgroud)

这工作正常,但我不知道如何通过我的配置创建行为app.config:

<system.serviceModel>
    <services>
        <service name="Service.EchoService">
            <endpoint address="net.pipe://localhost/EchoService" 
                      binding="netNamedPipeBinding"
                      contract="Contracts.IEchoService" 
                      behaviorConfiguration="LogBehaviour"
            />
        </service>
    </services>
    <extensions>
        <behaviorExtensions>
            <add name="logMessages" type="Service.LogMessagesExtensionElement, Service" />
        </behaviorExtensions>
    </extensions>
    <behaviors>
        <endpointBehaviors>
            <behavior name="LogBehaviour">
                <logMessages />
            </behavior>
        </endpointBehaviors>
    </behaviors>
</system.serviceModel>
Run Code Online (Sandbox Code Playgroud)
public class LogMessagesExtensionElement : BehaviorExtensionElement
{
    public override Type BehaviorType
    {
        get { return typeof(LogMessageBehavior); }
    }

    protected override object CreateBehavior()
    {
        //how do I create an instance using the IoC container here?
    }
}
Run Code Online (Sandbox Code Playgroud)

Ser*_*lov 4

如何将 ILogger 注入 LogMessageInspector 并将 LogMessageInspector 注入 LogMessageBehavior ?

该方法已在此处描述

更新

如果我错了,请纠正我,但我想问题归结为如何获得 Ninject 内核的实例BehaviorExtensionElement.CreateBehavior?答案取决于您的托管场景。如果托管在 IIS 下,您可以将类似的内容添加到您的NinjectWebCommon

public static StandardKernel Kernel
{
    get { return (StandardKernel)bootstrapper.Kernel; }
}
Run Code Online (Sandbox Code Playgroud)

由于您似乎是自托管的,因此您可能也想使用内核的静态实例。然而,在我看来,这并不是一个好主意。

实际上,我会投票支持您自己的方法并以编程方式配置行为,除非BehaviorExtensionElement有必要,因为您需要能够通过配置文件配置行为。

这太过分了吗?

这取决于,但如果您要对实现进行单元测试,则绝对不是。