繁体   English   中英

如何在C#中创建异常处理和日志记录类

[英]How to create a exception handling and logging class in C#

我正在做一个小项目,我正在尝试创建一个处理异常和日志记录的层。

该层将位于用户界面和DAL之间,与BAL最为相似,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()在当前上下文中不存在。

对于这类事情,AOP(面向方面​​的编程,请参阅https://en.wikipedia.org/wiki/Aspect-oriented_programming )非常合适。

如果处理不当,这些都是横切关注的问题,它们会使代码混乱。

请参阅示例AOP框架PostSharp。 即使使用易于编码的免费版本。 还有一些内置的方面(可能需要付费),例如http://doc.postsharp.net/exception-tracing

一个简单的替代方法是使用Func或Action(在Console App中尝试):

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
        }
    }
}

编辑:根据问题中添加的代码,您可以通过一些小的修改来解决有关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();
    }
}

给定提供的代码,您不需要InitiateCallobject[] parms参数。 函数调用所需的任何参数均在Func<T>

就个人而言,我认为应该以两种方式进行日志记录:

  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"));
            }
        }
    }

然后,如果我想记录某些内容,则可以这样使用,而无需AOP:

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM