2016-10-13 7 views
0

Я работаю над небольшим проектом, я пытаюсь создать слой, который будет обрабатывать исключения и протоколирование.Как создать класс обработки исключений и ведения журнала в C#

Этот слой будет располагаться между пользовательским интерфейсом и DAL, в основном как BAL, который будет иметь общий метод, который затем инициирует дальнейший вызов уровня доступа к данным.

Некоторые вещи, как этот

Public Class ExceptionHandler 
{ 
//which should take a method name,parameters and return a object. 
Public T InitiateDatabaseCall(//method name as input,parameters) 
{ 
try 
{ 
//then make the call to the method using the input parameter and pass the parameters 
} 
catch(Exception e) 
{ 
// do logging 
} 
} 

Этот слой будет выступать в качестве центра хранилища для обработки и регистрации исключение. Я не могу создать метод, который я описал, эксперты могут предоставить некоторый фрагмент, который покажет случай этого сценария.

Отредактировано: С код добавлен

static void Main(string[] args) 
     { 

      BAL b = new BAL(); 
      var ll = b.GetFieldList("xxxxyyyy"); 

     } 





    public class BAL 
    { 
     public List<Fields> GetFieldList(string screen) 
     { 
      if(!string.IsNullOrEmpty(screen)) 
      { 
       ExceptionHandler.InitiateCall(() =>GetList(screen))); 
      } 
     } 

    } 


    public static class ExceptionHandler 
    { 
     public T InitiateCall<T>(Func<T>method,object[] parms) where T : object 
     { 
      try 
      { 
       return method.Invoke(); 
      } 
      catch(Exception ex) 
      { 
       return default(T); 
      } 
     } 
    } 

    public class DAL 
    { 

     public List<Fields> GetList(string name) 
     { 
      VipreDBDevEntities context = new VipreDBDevEntities(); 
      return context.Database.SqlQuery<Fields>("SCREEN_FIELDS_SELECT @SCREEN_NAME", name).ToList(); 
     } 
    } 

Это дает ошибку GetList() не существует в текущем контексте.

ответ

0

Для таких вещей AOP (Аспектно-ориентированное программирование, см. https://en.wikipedia.org/wiki/Aspect-oriented_programming) является действительно хорошей подгонкой.

Это сквозные проблемы, которые являются загромождением кода, если не выполнены должным образом.

См. Пример AOP framework PostSharp. Даже с бесплатной версией, которую просто кодировать. Для этого есть (могут быть оплачены) встроенные аспекты, например http://doc.postsharp.net/exception-tracing.

Простая альтернатива с помощью Func или действий (попробовать его в App Console):

static void Main(string[] args) 
{ 
    ExceptionHandler.InitiateDatabaseCall(() => CallDb("Dummy")); 
    ExceptionHandler.InitiateDatabaseCall<int>(() => { throw new InvalidOperationException(); }); 
} 

int CallDb(string justToShowExampleWithParameters) 
{ 
    return 5; 
} 

public static class ExceptionHandler 
{ 
    public static T InitiateDatabaseCall<T>(Func<T> method) 
    { 
     try 
     { 
      return method.Invoke(); 
     } 
     catch (Exception e) 
     { 
      // do logging 
      Console.WriteLine(e.Message); 
      return default(T); // or `throw` to pass the exception to the caller 
     } 
    } 
} 

Edit: на основе вашего добавленным кода в вопросе вы можете решить ошибку о GetList() с некоторыми незначительными изменениями:

static void Main(string[] args) { 
    BAL b = new BAL(); 
    var ll = b.GetFieldList("xxxxyyyy"); 
} 

public class BAL 
{ 
    public List<Fields> GetFieldList(string screen) 
    { 
     if (!string.IsNullOrEmpty(screen)) 
     { 
      return ExceptionHandler.InitiateCall(() => new DAL().GetList(screen)); // Slight modification of your code here 
     } 
     else 
     { 
      return null; // or whatever fits your needs 
     } 
    } 
} 

public class ExceptionHandler 
{ 
    public static T InitiateCall<T>(Func<T> method) 
    { 
     try 
     { 
      return method.Invoke(); 
     } 
     catch (Exception ex) 
     { 
      //log 
      return default(T); 
     } 
    } 
} 

public class DAL 
{ 
    public List<Fields> GetList(string name) 
    { 
     VipreDBDevEntities context = new VipreDBDevEntities(); 
     return context.Database.SqlQuery<Fields>("SCREEN_FIELDS_SELECT @SCREEN_NAME", name).ToList(); 
    } 
} 

Вам не нужно параметр object[] parms в InitiateCall учитывая при условии код. Любые PARAMATERS, необходимые для вызова метода приведены в Func<T>

+0

Почему downvote? –

+0

, что довольно близко к тому, что я думал, я отредактировал свой вопрос с последним, есть ошибка, однако, о методе .... посмотрите – ankur

+0

GetList() определен в другом классе, поэтому 'ExceptionHandler.InitiateCall (() => GetList (экран))); 'необходимо изменить на' return ExceptionHandler.InitiateCall (() => новый DAL(). GetList (screen)); ' –

0

Лично я думаю, что Loging должно быть сделано двумя способами:

  1. Шаг регистрации (при входе в какой-то шаг в вашем коде)

  2. Область регистрации (при входе в систему начать/конец некоторого кода или время)

Таким образом, я всегда выбираю создать класс ILogger с этими двумя способами:

public sealed class Logger : ILogger 
    { 
     private readonly Serilog.ILogger _seriLogger; 

     public Logger(Serilog.ILogger seriLogger) 
     { 
      _seriLogger = seriLogger; 
     } 

     public void Debug(string format, params object[] args) 
     { 
      _seriLogger.Debug(format, args); 
     } 

     public void Info(string format, params object[] args) 
     { 
      _seriLogger.Information(format, args); 
     } 

     public void Warn(string format, params object[] args) 
     { 
      _seriLogger.Warning(format, args); 
     } 

     public void Error(Exception e, string format, params object[] args) 
     { 
      _seriLogger.Error(e, format, args); 
     } 

     public void Fatal(Exception e, string format, params object[] args) 
     { 
      _seriLogger.Fatal(e, format, args); 
     } 

     public IDisposable GetScope(string name, long timeout = 0) 
     { 
      return new LoggerScope(this, name, timeout); 
     } 
    } 

    internal class LoggerScope : IDisposable 
    { 
     private readonly ILogger _logger; 

     private readonly string _name; 

     private readonly long _timeout; 

     private readonly Stopwatch _sw; 

     private bool ExceedScope 
     { 
      get { return _timeout > 0; } 
     } 

     public LoggerScope(ILogger logger, string name, long timeout) 
     { 
      _logger = logger; 
      _name = name; 
      _timeout = timeout; 

      if (!ExceedScope) 
      { 
       _logger.Debug("Start execution of {0}.", name); 
      } 
      _sw = Stopwatch.StartNew(); 
     } 

     public void Dispose() 
     { 
      _sw.Stop(); 

      if (ExceedScope) 
      { 
       if (_sw.ElapsedMilliseconds >= (long)_timeout) 
       { 
        _logger.Debug("Exceeded execution of {0}. Expected: {1}ms; Actual: {2}ms.", _name, _timeout.ToString("N"), _sw.Elapsed.TotalMilliseconds.ToString("N")); 
       } 
      } 
      else 
      { 
       _logger.Debug("Finish execution of {0}. Elapsed: {1}ms", _name, _sw.Elapsed.TotalMilliseconds.ToString("N")); 
      } 
     } 
    } 

Тогда, если я хочу что-то журнал, я использую его, как это, без АОП:

using(_log.GetScope("Some describable name")) 
{ 
    //Some code here 
} 
+0

Это не относится к обработке исключений. Я думаю, что вопрос состоит в том, чтобы создать какую-то оболочку метода для записи обработки исключений и регистрации исключения, один раз и использовать его для многих методов. –

Смежные вопросы