如何在C#中创建异常处理和日志记录类(How to create a exception handling and logging class in 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()在当前上下文中不存在。

I am working on a small project, I am trying to create a layer that will handle exception and logging.

This layer will sit in between User interface and DAL, mostly like BAL which will have some generic method that will then initiate further call to Data access layer.

Some thing like this

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

This layer will act as center repository to handle and log exception. I am not able to create the method that i described can experts provide some snippet that will show case this scenario.

Edited: With code added

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

It gives error GetList() does not exist in current context.

最满意答案

对于这些类型的东西,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(); } }

根据提供的代码,您不需要InitiateCall的object[] parms参数。 你需要的方法调用的参数在Func<T>

For these kind of things AOP (Aspect Oriented Programming, see https://en.wikipedia.org/wiki/Aspect-oriented_programming) is a really good fit.

These are cross-cutting concerns that are cluttering code if not done properly.

See for an example AOP framework PostSharp. Even with the free version that is simple to code. There are also (might be paid) build-in aspects for that, like http://doc.postsharp.net/exception-tracing.

A simple alternative is using a Func or Action (try it out in a 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 } } }

Edit: based on your added code in the question you can solve the error about GetList() by some minor modifications:

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

You don't need the object[] parms parameter in InitiateCall given the provided code. Any paramaters you need for the method call are given in the Func<T>

更多推荐