1. 程式人生 > >WCF自定義Attribute記錄日誌或異常

WCF自定義Attribute記錄日誌或異常

1、定義一個attribute,同時繼承介面 IOperationBehavior

[AttributeUsage(AttributeTargets.Method)]
    public class RecordAttribute : Attribute, IOperationBehavior
    {

        private readonly string _operationName;
        private readonly RecordType _recordType;

        public RecordAttribute(string methodname, RecordType recordType)
        {
            _operationName = methodname;
            _recordType = recordType;
        }

        protected RecordInvoker CreateInvoker(IOperationInvoker oldInvoker)
        {
            return new RecordInvoker(oldInvoker, _operationName, _recordType);
        }

        public void Validate(OperationDescription operationDescription)
        {

        }

        public void ApplyDispatchBehavior(OperationDescription operationDescription, DispatchOperation dispatchOperation)
        {
            IOperationInvoker oldInvoker = dispatchOperation.Invoker;
            dispatchOperation.Invoker = CreateInvoker(oldInvoker);
        }

        public void ApplyClientBehavior(OperationDescription operationDescription, ClientOperation clientOperation)
        {

        }

        public void AddBindingParameters(OperationDescription operationDescription, BindingParameterCollection bindingParameters)
        {

        }
    }

2. 定義RecordInvoker ,繼承IOperationInvoker
    public class RecordInvoker : IOperationInvoker
    {

        private readonly IOperationInvoker _mOldInvoker;
        private readonly string _operationName;
        private readonly RecordType _recordType;

        protected void PreInvoke(object instance, object[] inputs)
        {

            if (_recordType == RecordType.Log || _recordType == RecordType.LogAndException)
            {
                //記錄日誌
            }

        }

        protected void PostInvoke(object instance, object returnedValue, object[] outputs, Exception err)
        {

            if (err != null && (_recordType == RecordType.Exception || _recordType == RecordType.LogAndException))    //如果有異常
            {
                //記錄異常
            }

        }

        public RecordInvoker(IOperationInvoker oldInvoker, string operationName, RecordType recordType)
        {
            _mOldInvoker = oldInvoker;
            _operationName = operationName;
            _recordType = recordType;
        }

        public object[] AllocateInputs()
        {
            return _mOldInvoker.AllocateInputs();
        }

        public object Invoke(object instance, object[] inputs, out object[] outputs)
        {

            PreInvoke(instance, inputs);
            object returnedValue = null;
            var outputParams = new object[] { };
            Exception exception = null;
            try
            {
                returnedValue = _mOldInvoker.Invoke(instance, inputs, out outputParams);
                outputs = outputParams;
                return returnedValue;
            }
            catch (Exception err)
            {
                outputs = null;
                exception = err;
                return null;
            }
            finally
            {
                PostInvoke(instance, returnedValue, outputParams, exception);
            }

        }

        public IAsyncResult InvokeBegin(object instance, object[] inputs, AsyncCallback callback, object state)
        {
            PreInvoke(instance, inputs);
            return _mOldInvoker.InvokeBegin(instance, inputs, callback, state);
        }

        public object InvokeEnd(object instance, out object[] outputs, IAsyncResult result)
        {
            object returnedValue = null;
            object[] outputParams = { };
            Exception exception = null;
            try
            {
                returnedValue = _mOldInvoker.InvokeEnd(instance, out outputs, result);
                outputs = outputParams;
                return returnedValue;
            }
            catch (Exception err)
            {
                outputs = null;
                exception = err;
                return null;
            }
            finally
            {
                PostInvoke(instance, returnedValue, outputParams, exception);
            }
        }

        public bool IsSynchronous
        {
            get
            {
                return _mOldInvoker.IsSynchronous;
            }
        }
    }

3、enum RecordType 定義如下
    public enum RecordType
    {

        None = 1,

        /// <summary>
        /// 記錄日誌
        /// </summary>
        Log = 2,

        /// <summary>
        /// 記錄異常
        /// </summary>
        Exception = 3,

        /// <summary>
        /// 記錄日誌和異常
        /// </summary>
        LogAndException = 4

    }

4、在需要記錄日誌的方法上加上自定義的特性:

[Record("Seo.CompanyService.GetCompanyWithCity", RecordType.Exception)]
        public IList<Company> GetCompanyWithCity(long cityId)