如何实现方法的前提条件?

时间:2012-05-31 16:34:41

标签: .net c#-4.0 code-contracts

我有一个班级

public class MyService  
{  
   public IList<Exception> ExList {get; private set;}

   public bool HasErrors { get { return ExList.Count > 0; } }

   public MyMethod()
   {
       ExList.Clear();
       //- do some logic ---
   }

}

我想调用MyMethod()并检查是否发生错误。像这样的东西

var service = new MyService();

service.MyMethod();

if(service.HasErrors)
{
    // - do some logic
}

service.MyMethod();

if(service.HasErrors)
{
    // - do some logic
}

但我必须写“ExList.Clear();”对MyService类中的每个方法进行manualy行。 问题是 - 有任何解决方案可以避免这种情况吗?

我需要像

这样的东西
public class MyService  
{  
   public IList<Exception> ExList {get; private set;}

   public bool HasErrors { get { return ExList.Count > 0; } }

   private void Precondition()
   {
       ExList.Clear();
   }

   public MyMethod()
   {           
       //- do some logic ---
   }

}

并且会为每个方法的调用自动调用Precondition()。

1 个答案:

答案 0 :(得分:1)

您可以研究的另一个工具是PostSharp。 PostSharp是一个AOP frawework,允许您定义自定义方面(属性)。

您会对OnMethodBoundaryAspect感兴趣。像下面这样的东西可以做到这一点。 args.Instance将是“正在执行该方法的实例”

public class ClearListPrecondition : OnMethodBoundaryAspect
{
    public override void OnEntry(MethodExecutionArgs args)
    {
        MyService service = args.Instance as MyService;
        if (service == null)
        {
            throw new InvalidOperationException(
              "This aspect can only execute on types of MyService");
        }

        service.ExList.Clear();
        base.OnEntry(args);
    }
}

然后,您将使用以下方面装饰您的服务方法:

[ClearListPrecondition]
public void MyMethod()
{
}

如果您选择将AOP的路径用于这样一项微不足道的任务,我强烈建议您重新考虑您的设计。

首先,应首选抛出异常,但如果您坚持,则可以从您的方法返回结果。

E.g。

public MethodResult MyMethod()
{
    ....
     if(errorHasOccured)
     {
          return new MethodResult() {Exceptions = exception};
     }
    ....
     return new MethodResult() {ResultOfMethod = ...};
}

public class MethodResult
{
   public IList<Exception> Exceptions {get; set;}
   public bool HasErrors { get { return ExList.Count > 0; } } 
   public string ResultOfMethod {get;set;}

}

您的消费者可以查看方法调用的结果:

var service = new MyService();

var result1 = service.MyMethod();

if(result1.HasErrors)
{
    // - do some logic
}

var result2 = service.MyMethod();

if(result2.HasErrors) 
{
    // - do some logic
}

这消除了重置服务状态的需要,因为它变为无状态(因此线程安全)