WCF自定義Attribute記錄日誌或異常
阿新 • • 發佈:2019-02-15
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)