gpt4 book ai didi

wcf - CaSTLe Windsor - 将记录器注入(inject) IErrorHandler

转载 作者:行者123 更新时间:2023-12-01 02:22:10 24 4
gpt4 key购买 nike

我在我的 Wcf 服务项目中使用 CaSTLe windsor 3.0。我使用 Topshelf 将其托管为 Windows 服务项目。我所有的 wcf 服务配置都在 app.config 文件中。
我正在使用城堡 wcffacility 并注册这样的服务 -

Container.AddFacility<WcfFacility>();
Container.AddFacility<LoggingFacility>(f => f.UseLog4Net());
container.Register(
Classes
.FromThisAssembly()
.Pick()
.If(x => x.IsClass
&& HasServiceContract(x))
.WithServiceDefaultInterfaces()
.Configure(c => c.AsWcfService().LifeStyle.HybridPerWcfOperationTransient()));

这会毫无问题地将 ILog(来自 log4net)注入(inject)我的服务,但无法注入(inject) IErrorHandler。

我添加了带有 IErrorHandler 的 ServiceBehaviour,以便我可以捕获用户未处理的异常并使用以下代码记录错误。
 #region IErrorHandler Members
public ILog Logger { get; set; }
public bool HandleError(Exception error)
{
if (error is FaultException)
return false; // Let WCF do normal processing

return true; // Fault message is already generated
}

public void ProvideFault(Exception error, MessageVersion version, ref Message fault)
{

var uniqueKey = UniqueKeyGenerator.Generate();

//create the custom wcfexception before passing that to client
var wcfException = new CustomServerException("Unknown Error has occured. Please contact your administrator!", uniqueKey);

//log the exception
Logger.Error(uniqueKey, error);


MessageFault messageFault = MessageFault.CreateFault(
new FaultCode("Sender"),
new FaultReason(wcfException.Message),
wcfException,
new NetDataContractSerializer());
fault = Message.CreateMessage(version, messageFault, null);

}

我查看了这个 stackoverflow post但它太旧了,没有发布答案,所以我发布了这个新问题。

更新

我用 grayAlien 提供的答案解决了这个问题(部分暂时)。
我所要做的就是
  • 将自定义服务行为类注册到城堡温莎。
    Container.Register(
    Component.For<IServiceBehavior>()
    .ImplementedBy<PassThroughExceptionHandlingBehaviour>()
    .Named("IServiceBehavior")
  • 从 app.config 文件中删除 serviceBehaviour 扩展。当我添加
    配置文件中的行为扩展,由于某种原因,城堡不是
    能够注入(inject)依赖项,而不是我认为 Wcf 正在创建新的
    实例和记录器公共(public)属性结果为空。

  • 它现在对我有用,但需要了解(将来)如何使用行为扩展来注入(inject)依赖项。

    最佳答案

    这是一个自托管示例,它可以完成我相信您正在尝试做的事情。这是一个控制台应用程序。您需要以管理员身份启动 Visual Studio,才能让 netsh 注册 localhost:55001

    我正在使用城堡 3.1。

    源代码文件:

    namespace WcfSelfHost
    {
    using System;
    using Castle.Windsor;
    using Castle.Facilities.WcfIntegration;
    using System.ServiceModel;
    using Castle.MicroKernel.Registration;
    using System.ServiceModel.Configuration;
    using System.ServiceModel.Description;
    using Castle.MicroKernel;

    public interface ILog
    {
    void LogMessage(string message);
    }

    public class ConsoleLogger : ILog
    {
    public void LogMessage(string message)
    {
    Console.WriteLine(message);
    }
    }

    [ServiceBehavior]
    public class CastleCreatedLoggingServiceBehavior : IServiceBehavior
    {
    private readonly ILog logger;

    public CastleCreatedLoggingServiceBehavior(ILog logger)
    {
    this.logger = logger;
    }

    public void AddBindingParameters(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase, System.Collections.ObjectModel.Collection<ServiceEndpoint> endpoints, System.ServiceModel.Channels.BindingParameterCollection bindingParameters)
    {
    this.logger.LogMessage("in AddBindingParameters");
    }

    public void ApplyDispatchBehavior(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase)
    {
    this.logger.LogMessage("in ApplyDispatchBehavior");
    }

    public void Validate(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase)
    {
    this.logger.LogMessage("in Validate");
    }
    }

    [ServiceContract]
    public interface IService
    {
    [OperationContract]
    void TheOneOperation(string data);
    }

    public class ServiceImplementation : IService
    {
    private readonly ILog logger;

    public ServiceImplementation(ILog logger)
    {
    this.logger = logger;
    }

    public void TheOneOperation(string data)
    {
    this.logger.LogMessage("service received message:");
    this.logger.LogMessage(data);
    }
    }

    public class ConsoleApplication
    {
    public static void Main()
    {
    //making this a variable to show the requirement that the names match
    string serviceName = "TheService";

    //configure the container with all the items we need
    IWindsorContainer container = new WindsorContainer()
    .AddFacility<WcfFacility>(f => f.CloseTimeout = TimeSpan.Zero)
    .Register(
    Component.For<CastleCreatedLoggingServiceBehavior>(),
    Component.For<ILog>()
    .ImplementedBy<ConsoleLogger>()
    .LifestyleSingleton(),
    Component.For<IService>()
    .ImplementedBy<ServiceImplementation>()
    .LifestyleSingleton()
    .Named(serviceName)
    );

    //setup our factory with that has knowledge of our kernel.
    DefaultServiceHostFactory factory = new DefaultServiceHostFactory(container.Kernel);

    //create a host for our service matching the name of the castle component. Not adding any additional base addresses.
    using (ServiceHostBase host = factory.CreateServiceHost(serviceName, new Uri[0]))
    {
    host.Open();
    Console.WriteLine("server listening for messages");


    //and here's the client..
    IWindsorContainer clientContainer = new WindsorContainer()
    .AddFacility<WcfFacility>(f => f.CloseTimeout = TimeSpan.Zero)
    .Register(
    Component.For<IService>()
    .AsWcfClient(WcfEndpoint.FromConfiguration("serviceEndpointDefinition"))
    );

    IService client = clientContainer.Resolve<IService>();
    client.TheOneOperation("data from client");
    Console.ReadLine();

    }
    }
    }
    }

    这是控制台应用程序的 app.config 文件。我们本可以在源代码中使用 fluent API 来配置所有这些,但是将服务和客户端配置分开是很正常的,所以我选择了配置文件路径。如果你想要一个 c# fluent API 版本,请告诉我。
    <?xml version="1.0" encoding="utf-8" ?>
    <configuration>
    <startup>
    <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5" />
    </startup>

    <system.serviceModel>
    <bindings>
    <basicHttpBinding>
    <binding name="overrideMessageSize_forBasicHttpBinding" maxBufferPoolSize="2147483647"
    maxReceivedMessageSize="2147483647"/>
    </basicHttpBinding>
    </bindings>

    <services>
    <service name="WcfSelfHost.ServiceImplementation">
    <host>
    <baseAddresses>
    <add baseAddress="http://localhost:55001/baseaddress"/>
    </baseAddresses>
    </host>

    <endpoint
    contract="WcfSelfHost.IService"
    binding="basicHttpBinding"
    bindingConfiguration="overrideMessageSize_forBasicHttpBinding"
    address="http://localhost:55001/baseaddress/serviceimplementation"
    />
    </service>
    </services>

    <client>
    <endpoint
    name="serviceEndpointDefinition"
    contract="WcfSelfHost.IService"
    binding="basicHttpBinding"
    bindingConfiguration="overrideMessageSize_forBasicHttpBinding"
    address="http://localhost:55001/baseaddress/serviceimplementation"
    />
    </client>

    </system.serviceModel>
    </configuration>

    关于wcf - CaSTLe Windsor - 将记录器注入(inject) IErrorHandler,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19632603/

    24 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com