使用IoC在WCF中实现错误处理程序

时间:2015-10-13 07:30:29

标签: c# wcf dependency-injection ioc-container simple-injector

我正在尝试按照本教程在我的WCF服务上实现错误处理程序: Implementing IErrorHandler 在这个错误处理程序中,我希望每个异常都能通过传递我的记录器来登录日志文件,实现ILogger(在我的情况下由NLog使用)。

现在的问题是我想使用依赖注入,将记录器作为构造函数参数,由我的IoC容器初始化(使用SimpleInjector)。

有谁可以帮我这个? (仅供参考......我对DI和IoC来说很新)

的ErrorHandler:

public class ErrorHandler : IErrorHandler, IServiceBehavior
{
    private readonly ILogger _logger;

    public ErrorHandler(ILogger logger)
    {
        _logger = logger;
    }

    public void AddBindingParameters(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase, Collection<ServiceEndpoint> endpoints, BindingParameterCollection bindingParameters)
    {
    }

    public void ApplyDispatchBehavior(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase)
    {
        IErrorHandler errorHandler = new ErrorHandler(_logger);

        foreach (ChannelDispatcherBase channelDispatcherBase in serviceHostBase.ChannelDispatchers)
        {
            var channelDispatcher = channelDispatcherBase as ChannelDispatcher;

            if (channelDispatcher != null)
            {
                channelDispatcher.ErrorHandlers.Add(errorHandler);
            }
        }
    }

    public bool HandleError(Exception error)
    {
        _logger.Error("EXCEPTION: ", error);
        return true;
    }

    public void Validate(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase)
    {
    }

    public void ProvideFault(Exception error, MessageVersion version, ref Message fault)
    {
        // Shield the unknown exception
        FaultException faultException = new FaultException("Server error encountered. All details have been logged.");
        MessageFault messageFault = faultException.CreateMessageFault();

        fault = Message.CreateMessage(version, messageFault, faultException.Action);
    }
}


ErrorHandlerElement:

public class ErrorHandlerElement : BehaviorExtensionElement
{
    private readonly ILogger _logger;

    public ErrorHandlerElement(ILogger logger)
    {
        _logger = logger;
    }

    protected override object CreateBehavior()
    {
        return new ErrorHandler(_logger);
    }

    public override Type BehaviorType
    {
        get
        {
            return typeof(ErrorHandler);
        }
    }
}

的Web.config

与教程相同,但在behaviorExtension中使用我自己的类型

的Global.asax.cs

创建SimpleInjector容器并注册类型

1 个答案:

答案 0 :(得分:0)

我没有完整的答案,因为我不认识温莎。我通过使用构建策略扩展使用Unity完成了这项工作。我认为温莎有类似的东西。

请参阅http://www.primordialcode.com/blog/post/unity-wcf-service-resolution-container-extension/有关如何与WCF一起使用构建策略的详细信息。

以下是我以前能够在解析之前配置服务主机的代码段。该代码支持配置和添加服务端点和行为,作为通过容器解析主机解析的接口。

请注意,我通常不会使用app.config或等效内容。

public class WcfServiceHostBuildPlanPolicy<TInterface, TImplementation> : IBuildPlanPolicy
    where TInterface : class
    where TImplementation : class, TInterface
{
    private class ServiceEndpoint
    {
        public string Address { get; set; }
        public Binding Binding { get; set; }
        public Type Type { get; set; }
    }

    private readonly List<ServiceEndpoint> endpoints;
    private readonly List<Type> behaviors;

    /// <summary>
    /// Adds a new service behavior.
    /// </summary>
    public void AddBehavior<T>() where T : IServiceBehavior
    {
        behaviors.Add(typeof (T));
    }

    public void AddServiceEndpoint(Type type, string address, Binding binding)
    {
        endpoints.Add(new ServiceEndpoint
        {
            Address = address,
            Binding = binding,
            Type = type
        });

    }

    public WcfServiceHostBuildPlanPolicy()
    {
        m_Behaviors = new List<Type>();
        m_Endpoints = new List<ServiceEndpoint>();
    }

    public void BuildUp(IBuilderContext context)
    {
        if (context.Existing == null)
        {
            // build up dependencies
            var behavior = context.NewBuildUp<DIServiceBehavior<TInterface, TImplementation>>();

            // create new DIServiceHost
            var serviceHost = new DIServiceHost<TInterface, TImplementation>(behavior);

            // add behaviors to ServiceHost
            foreach (var behaviorType in behaviors)
            {
                var newBehavior = context.NewBuildUp(new NamedTypeBuildKey(behaviorType)) as IServiceBehavior;
                serviceHost.Description.Behaviors.Add(newBehavior);
            }

            // add service endpoints to ServiceHost
            endpoints.ForEach(s => serviceHost.AddServiceEndpoint(s.Type, s.Binding, s.Address));

            context.Existing = serviceHost;
        }
    }
}