katie77
katie77

Reputation: 1811

How do you implement a base method that should be called for all the methods?

I have a Product Service. On each call to Service, I want to call a method. In this case, I am logging. I am looking for a way, not to write the using statement in each method. But I still want the Logging to happen on each call. How do I do this?

    public class ProductService : IProductService
{
    public IList<Product> GetProductsByBrand(int BrandID)
    {
        using (new Logging())
        {
            // Get a list of products By Brand
        }
        return new List<Product>();
    }

    public IList<Product> Search(string ProductName)
    {
        using (new Logging())
        {
            // Search
        }
        return new List<Product>();
    }

    public static string OrderProducts(IList<Order> Orders, Payment paymentDetials)
    {
        string AuthCode;
        using (new Logging())
        {
            // Order and get the AuthCode
        }
        AuthCode = "";
        return AuthCode;
    }
}

Upvotes: 2

Views: 240

Answers (3)

tallseth
tallseth

Reputation: 3665

You can create a dynamic proxy. See this article for instructions.

Upvotes: 0

Jason Turan
Jason Turan

Reputation: 1352

Have you heard of AOP (Aspect Oriented Programming)? It's a way of implementing cross cutting concerns as reusable Aspects that wrap around the target type and perform additional processing before or after the method that they are wrapping.

http://en.wikipedia.org/wiki/Decorator_pattern

Within a WCF environment this is typically done by applying "Behaviors" to your service class. In this case I would suggest the IOperationBehavior interface using an attribute that implements IParameterInspector in order to look at the parameters before they are passed the service instance is created and called. Here is a link to a useful article that goes into more depth regarding your options for extending the wcf message pipeline.

http://msdn.microsoft.com/en-us/magazine/cc163302.aspx

//Attribute class
public class LogOperationBehavior : Attribute, IOperationBehavior, IParameterInspector {

public void AddBindingParameters(OperationDescription operationDescription, System.ServiceModel.Channels.BindingParameterCollection bindingParameters) {
    return;
}

public void ApplyClientBehavior(OperationDescription operationDescription, System.ServiceModel.Dispatcher.ClientOperation clientOperation) {
    //clientOperation.ParameterInspectors.Add(new ClientParameterInspector());            
}

public void ApplyDispatchBehavior(OperationDescription operationDescription, System.ServiceModel.Dispatcher.DispatchOperation dispatchOperation) {
    dispatchOperation.ParameterInspectors.Add(this);
}

public void Validate(OperationDescription operationDescription) {
    return;
}



#region IParameterInspector Members

public void AfterCall(string operationName, object[] outputs, object returnValue, object correlationState) {
   //perform logging after
}

public object BeforeCall(string operationName, object[] inputs) {
    //perform logging before
    return null;
}

#endregion

}

  public class BusinessOperation : IBusinessOperation {

    //Apply to your service via an attribute
    [LogOperationBehavior]
    public DivideResponse DivideTwoNumbers(DivideRequest dr) {            
        return new DivideResponse() {
            Answer = dr.Numerator/ dr.Demoninator2,              
        };
    }

Upvotes: 3

tallseth
tallseth

Reputation: 3665

Have you considered creating a logging proxy? It would look something like this:

public class LoggingProductService : IProductService
{
    private readonly IProductService _core;

    public LoggingProductService(IProductService core)
    {
        _core = core;
    }

    public IList<Product> GetProductsByBrand(int BrandID)
    {
        Log("Getting products for brand " + BrandId);
        return _core.GetProductsByBrand(BrandId);
    }

    //other IProductService methods here, all logging and delegating to _core

    private void Log(string message)
    {
        using (var log = new Logging())
        {
            log.Write(message);
        }
    }
}

Of course, I don't entirely understand your Logging interface, so fill in the appropriate guesses with correct code. You also may not want to create and Dispose a Logging that often, I don't know.

Upvotes: 1

Related Questions