使用 WCF 中的类级属性实现 IErrorHandler

发布于 2024-09-08 20:27:03 字数 6022 浏览 3 评论 0原文

没有运气通过配置文件让它工作,所以决定尝试通过类级别属性走更稳健的路线。如果我能让这个工作正常,这显然是在服务层中将异常包装在故障中的好方法,而无需重复大量代码。

然而,属性中的代码似乎永远不会运行 - 尽管定义属性的代码编译得很好并且被 IDE 识别。关于解决这个问题,我已经没有什么可读的了——只是要处理的异常,然后就会被抛出。

我还借用并砍掉了在 rorys 网站上的 CodePlex 上找到的一段代码,以简化该问题,而不改变其功能(删除冗余重载),

这让我发疯......请帮忙! :D

Rory Primrose - 属性实现

< a href="http://www.neovolve.com/post/2008/04/07/implementing-ierrorhandler.aspx" rel="nofollow noreferrer">Rory Primrose - IErrorHandlerImplementation

代码:

Service 接口和实现

[ServiceContract]
public interface IService1
{
    [OperationContract]
    [FaultContract(typeof(FaultException))]
    string GetData(int value);
}

[ErrorHandler(typeof(KnownErrorHandler))]
public class Service1 : IService1
{
    public string GetData(int value)
    {
        throw new Exception("This exception should get handled.");
    }
}

KnownErrorHandler 实现:

public class KnownErrorHandler : IErrorHandler
{
    public bool HandleError(Exception error)
    {
        Trace.WriteLine(error.ToString());  
       return true;  
    }

    public void ProvideFault(Exception error, System.ServiceModel.Channels.MessageVersion version, ref System.ServiceModel.Channels.Message fault)
    {
        FaultException faultException = new FaultException("Server error encountered. All details have been logged.");  
         MessageFault messageFault = faultException.CreateMessageFault();  
         fault = Message.CreateMessage(version, messageFault, faultException.Action); 
    }
}

属性定义 - 怀疑问题就在这里。我相当确定这与我使用这段代码的方式有关。

   [AttributeUsage(AttributeTargets.Class)]
    public sealed class ErrorHandler : Attribute, IServiceBehavior
    { 
        public ErrorHandler(Type errorHandler)
        {
            if (errorHandler == null)
            {throw new ArgumentNullException("errorHandler");}
            Type[] errorHandlerTypes = new[] { errorHandler };
            Initialize(errorHandlerTypes);
        }   

        public void AddBindingParameters(
            ServiceDescription serviceDescription,
            ServiceHostBase serviceHostBase,
            Collection<ServiceEndpoint> endpoints,
            BindingParameterCollection bindingParameters)
        {
            // Nothing to do here
        }

        public void ApplyDispatchBehavior(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase)
        {
            if (serviceHostBase == null)
            {
                throw new ArgumentNullException("serviceHostBase");
            }

            // Loop through each channel dispatcher
            for (Int32 dispatcherIndex = 0; dispatcherIndex < serviceHostBase.ChannelDispatchers.Count; dispatcherIndex++)
            {
                // Get the dispatcher for this index and cast to the type we are after
                ChannelDispatcher dispatcher = (ChannelDispatcher)serviceHostBase.ChannelDispatchers[dispatcherIndex];

                // Loop through each error handler
                for (Int32 typeIndex = 0; typeIndex < ErrorHandlerTypes.Count; typeIndex++)
                {
                    Type errorHandlerType = ErrorHandlerTypes[typeIndex];

                    // Create a new error handler instance
                    IErrorHandler handler = (IErrorHandler)Activator.CreateInstance(errorHandlerType);

                    // Add the handler to the dispatcher
                    dispatcher.ErrorHandlers.Add(handler);
                }
            }
        }

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


        private void Initialize(Type[] errorHandlerTypes)
        {
            const String ErrorHandlerTypesParameterName = "errorHandlerTypes";

            if (errorHandlerTypes == null)
            {
                throw new ArgumentNullException(ErrorHandlerTypesParameterName);
            }

            if (errorHandlerTypes.Length == 0)
            {
                throw new ArgumentOutOfRangeException(ErrorHandlerTypesParameterName);
            }

            List<String> typeNames = new List<String>(errorHandlerTypes.Length);

            // Loop through each item supplied
            for (Int32 index = 0; index < errorHandlerTypes.Length; index++)
            {
                Type errorHandlerType = errorHandlerTypes[index];

                // Check if the item supplied is null
                if (errorHandlerType == null)
                {
                    throw new ArgumentNullException(ErrorHandlerTypesParameterName);
                }

                // Check if the type doesn't define the IErrorHandler interface
                if (typeof(IErrorHandler).IsAssignableFrom(errorHandlerType) == false)
                {
                    // We can't use this type
                    throw new InvalidCastException();
                }

                String assemblyQualifiedName = errorHandlerType.AssemblyQualifiedName;

                if (typeNames.Contains(assemblyQualifiedName) == false)
                {
                    typeNames.Add(assemblyQualifiedName);
                }
                else
                {
                    throw new ArgumentException(
                        String.Format(CultureInfo.CurrentCulture, "Duplicate ErrorType Provided", assemblyQualifiedName));
                }
            }

            // Store the types
            ErrorHandlerTypes = new ReadOnlyCollection<Type>(errorHandlerTypes);
        }

        /// <summary>
        /// Gets the error handler types.
        /// </summary>
        /// <value>
        /// The error handler types.
        /// </value>
        public ReadOnlyCollection<Type> ErrorHandlerTypes
        {
            get;
            private set;
        }
    }

Had no luck with getting it working via config files, so decided to attempt to go the more robust route of doign it via class level attributes. If I can get this working it is clearly a great way of wrapping exceptions in Faults in the service layer withou trepeating lots of code.

However the code in the attribute never seems to get run - despite the code that defines the attribute compiling perfectly well and being recognised by the IDE. I have ran out of things to read regarding solving this - the exception just to be handled and just gets thrown.

I have also borrowed and chopped down a piece of code found on CodePlex that is on rorys site to simplify it for this problem without changing its function (removed redundant overloads)

this is driving me insane ... please help! :D

Rory Primrose - attribute implementation

Rory Primrose - IErrorHandlerImplementation

The code:

The Service interface and implementation

[ServiceContract]
public interface IService1
{
    [OperationContract]
    [FaultContract(typeof(FaultException))]
    string GetData(int value);
}

[ErrorHandler(typeof(KnownErrorHandler))]
public class Service1 : IService1
{
    public string GetData(int value)
    {
        throw new Exception("This exception should get handled.");
    }
}

KnownErrorHandler Implementation:

public class KnownErrorHandler : IErrorHandler
{
    public bool HandleError(Exception error)
    {
        Trace.WriteLine(error.ToString());  
       return true;  
    }

    public void ProvideFault(Exception error, System.ServiceModel.Channels.MessageVersion version, ref System.ServiceModel.Channels.Message fault)
    {
        FaultException faultException = new FaultException("Server error encountered. All details have been logged.");  
         MessageFault messageFault = faultException.CreateMessageFault();  
         fault = Message.CreateMessage(version, messageFault, faultException.Action); 
    }
}

Attribute definition - doubt the problem is here. I am fairly sure it is in how i am using this piece of code.

   [AttributeUsage(AttributeTargets.Class)]
    public sealed class ErrorHandler : Attribute, IServiceBehavior
    { 
        public ErrorHandler(Type errorHandler)
        {
            if (errorHandler == null)
            {throw new ArgumentNullException("errorHandler");}
            Type[] errorHandlerTypes = new[] { errorHandler };
            Initialize(errorHandlerTypes);
        }   

        public void AddBindingParameters(
            ServiceDescription serviceDescription,
            ServiceHostBase serviceHostBase,
            Collection<ServiceEndpoint> endpoints,
            BindingParameterCollection bindingParameters)
        {
            // Nothing to do here
        }

        public void ApplyDispatchBehavior(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase)
        {
            if (serviceHostBase == null)
            {
                throw new ArgumentNullException("serviceHostBase");
            }

            // Loop through each channel dispatcher
            for (Int32 dispatcherIndex = 0; dispatcherIndex < serviceHostBase.ChannelDispatchers.Count; dispatcherIndex++)
            {
                // Get the dispatcher for this index and cast to the type we are after
                ChannelDispatcher dispatcher = (ChannelDispatcher)serviceHostBase.ChannelDispatchers[dispatcherIndex];

                // Loop through each error handler
                for (Int32 typeIndex = 0; typeIndex < ErrorHandlerTypes.Count; typeIndex++)
                {
                    Type errorHandlerType = ErrorHandlerTypes[typeIndex];

                    // Create a new error handler instance
                    IErrorHandler handler = (IErrorHandler)Activator.CreateInstance(errorHandlerType);

                    // Add the handler to the dispatcher
                    dispatcher.ErrorHandlers.Add(handler);
                }
            }
        }

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


        private void Initialize(Type[] errorHandlerTypes)
        {
            const String ErrorHandlerTypesParameterName = "errorHandlerTypes";

            if (errorHandlerTypes == null)
            {
                throw new ArgumentNullException(ErrorHandlerTypesParameterName);
            }

            if (errorHandlerTypes.Length == 0)
            {
                throw new ArgumentOutOfRangeException(ErrorHandlerTypesParameterName);
            }

            List<String> typeNames = new List<String>(errorHandlerTypes.Length);

            // Loop through each item supplied
            for (Int32 index = 0; index < errorHandlerTypes.Length; index++)
            {
                Type errorHandlerType = errorHandlerTypes[index];

                // Check if the item supplied is null
                if (errorHandlerType == null)
                {
                    throw new ArgumentNullException(ErrorHandlerTypesParameterName);
                }

                // Check if the type doesn't define the IErrorHandler interface
                if (typeof(IErrorHandler).IsAssignableFrom(errorHandlerType) == false)
                {
                    // We can't use this type
                    throw new InvalidCastException();
                }

                String assemblyQualifiedName = errorHandlerType.AssemblyQualifiedName;

                if (typeNames.Contains(assemblyQualifiedName) == false)
                {
                    typeNames.Add(assemblyQualifiedName);
                }
                else
                {
                    throw new ArgumentException(
                        String.Format(CultureInfo.CurrentCulture, "Duplicate ErrorType Provided", assemblyQualifiedName));
                }
            }

            // Store the types
            ErrorHandlerTypes = new ReadOnlyCollection<Type>(errorHandlerTypes);
        }

        /// <summary>
        /// Gets the error handler types.
        /// </summary>
        /// <value>
        /// The error handler types.
        /// </value>
        public ReadOnlyCollection<Type> ErrorHandlerTypes
        {
            get;
            private set;
        }
    }

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文