0

On the return of an object I want to ensure an action is performed just before if is returned. Is there a way to override the default return of an object to perform that?

for example

//In the constructor I set a query start time
var items = new ListReturnDTO<Product>();

    ....

//I want to set a query end time, but without the need to set the variable in code as it could be forgotten. 
return items;

EDIT:

      //I set the QueryStartTime in the constructor
      var items = new ListReturnDTO<Product>();

            items.TotalItem = 11;

            ........

            items.data.Add(new Product { SKU = "000006", Description = "this is the test product 7, a rare breed of product", Price = 65.00, QuantityLeft = 3, Title = "Test Product 7", IsPreview = false });
            items.data.Add(new Product { SKU = "000007", Description = "this is the test product 8, a rare breed of product", Price = 7.00, QuantityLeft = 30, Title = "Test Product 8", IsPreview = false });

            //force a delay to replicate talking to external source
            Thread.Sleep(2000);

            //Currently i set QueryEndTime Here
            items.QueryEndTime = DateTime.UtcNow.TimeOfDay;

            //But i want it to be done automatically on the return (like how I can set QueryStartTime in the constructor, is there an equivalent/an override for the return)
            return Task.FromResult(items);
markblue777
  • 829
  • 3
  • 13
  • 28
  • 3
    Can you elaborate what exactly you mean by _"override the default return of an object"_? What exactly do is the "query start time" and "query end time"? – CodeCaster Jan 22 '19 at 10:57

2 Answers2

3

As per my understanding of question

At the end of method call some code automatically. Or more specifically if return type of the method is not void, perform some action. So in given example it should update QueryEndTime.

This concept is seems like aspect oriented programming. One of the library, you might want to try, could be Postsharp. There are few others as well.

Postsharp has method decorator, which can Inject Behaviors Before and After Method Execution. Sample code from previous link

[PSerializable]
public class LoggingAspect : OnMethodBoundaryAspect
{

  public override void OnEntry(MethodExecutionArgs args)
  {
     Console.WriteLine("The {0} method has been entered.", args.Method.Name);
  }

  public override void OnSuccess(MethodExecutionArgs args)
  {
      Console.WriteLine("The {0} method executed successfully.", args.Method.Name);
  }

  public override void OnExit(MethodExecutionArgs args)
  {
     Console.WriteLine("The {0} method has exited.", args.Method.Name);
  }     

  public override void OnException(MethodExecutionArgs args)
  {
      Console.WriteLine("An exception was thrown in {0}.", args.Method.Name);
  }

}

static class Program
{
   [LoggingAspect]
   static void Main()
   {
     Console.WriteLine("Hello, world.");
   }
}

Now coming to your example code, if it is one time look at this answer.

Chaturvedi Dewashish
  • 1,469
  • 2
  • 15
  • 39
  • Ahh thanks a lot, I thought there would be something like this if there was not a native ability to do it. I will have a look at it and see what's what. Thanks – markblue777 Jan 22 '19 at 11:59
  • Perfect. The only problem is Postsharp. The free edition is very limited. – andre Jan 22 '19 at 13:22
0

So you have multiple methods or classes who perform some queries and populate your data. You want to log the query start and end times in your return object, which will always be of type ListReturnDTO<T>, where T is the type of entity being queried.

Your question lacks a little context, but assuming you utilize something like a repository pattern, you could make your base repository look like this, with a publicly callable method which in turn calls an abstract method that must be implemented by a derived class, offloading the actual work to a more specialized type:

public abstract class BaseRepository<TEntity>
{
    public async Task<ListReturnDTO<TEntity>> QueryDataAsync()
    {
        var items = new ListReturnDTO<TEntity>();

        items.QueryStartTime = DateTime.UtcNow;

        await QueryAndPopulateDataAsync(items);

        items.QueryEndTime = DateTime.UtcNow;

        return items;
    }

    protected abstract Task QueryAndPopulateDataAsync(ListReturnDTO<TEntity> container);
}

Where you have one method, which is always called, QueryDataAsync(), which assigns the properties you always want assigned.

Now to implement an actual repository, you inherit the base one and do the actual querying in QueryAndPopulateDataAsync():

public class ProductRepository : BaseRepository<Product>
{
    protected override async Task QueryAndPopulateDataAsync(ListReturnDTO<TEntity> container)
    {
        container.TotalItem = 11;

        ........

        container.data.Add(new Product { SKU = "000006", Description = "this is the test product 7, a rare breed of product", Price = 65.00, QuantityLeft = 3, Title = "Test Product 7", IsPreview = false });
        container.data.Add(new Product { SKU = "000007", Description = "this is the test product 8, a rare breed of product", Price = 7.00, QuantityLeft = 30, Title = "Test Product 8", IsPreview = false });

        //force a delay to replicate talking to external source
        Thread.Sleep(2000);
    }
}

And call it like this:

var repo = new ProductRepository();
var data = await repo.QueryDataAsync();

And data will have its QueryStartTime, QueryEndTime and data properties assigned.

CodeCaster
  • 147,647
  • 23
  • 218
  • 272
  • Ok I can see that and thought of something similar, but i was after something that did not need a specific calls to methods to run the functionality. I Just want this process to be as automated as possible as. I will look at the library that was mentioned above but if it does not fit I will roll back to the above. Cheers – markblue777 Jan 22 '19 at 12:22