简体   繁体   中英

How to implement precondition for a method?

I have a class

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

}

And I want to call MyMethod() and check if errors was occured. Something like this

var service = new MyService();

service.MyMethod();

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

service.MyMethod();

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

But I have to write "ExList.Clear();" row manualy for every method in MyService class. And the question is - Are any solution to avoid this?

I need something like

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

}

And Precondition() would be invoked automatically for each method's call.

Another tool you could look into is PostSharp. PostSharp is an AOP frawework that allows you to define custom aspects (attributes).

You'll be interested in OnMethodBoundaryAspect . Something like below should do the trick. args.Instance will be "the instance on which the method is being executed"

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

You would then decorate your service methods with this aspect:

[ClearListPrecondition]
public void MyMethod()
{
}

If you choose to take the path of AOP for such a trivial task, I strongly recommend you re-thinking your design.

Firstly, throwing exceptions should be preferred, but if you insist, you could return a result from your method.

Eg

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

}

Your consumers can check the result of a method call:

var service = new MyService();

var result1 = service.MyMethod();

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

var result2 = service.MyMethod();

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

This removes the need to reset the state of your service as it becomes stateless (and therefore threadsafe)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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