Search code examples
c#aop

Aspect Oriented Programming in c#


I have a class in SampleClassLibrary called DataLayerClass.This class has an attribute for tracing purpose.

 [Tracing]
public class DataLayerClass:ContextBoundObject
{
    public string DataLayerMethod()
    {
        return "Hi";
    }
}

This attribute implemented using AOP.The code will be like this:

 internal class TracingAspect : IMessageSink
{
    internal TracingAspect(IMessageSink next)
    {
        m_next = next;
    }

    #region Private Vars
    private IMessageSink m_next;
    private String m_typeAndName;
    #endregion // Private Vars

    #region IMessageSink implementation
    public IMessageSink NextSink
    {
        get { return m_next; }
    }

    public IMessage SyncProcessMessage(IMessage msg)
    {
        Preprocess(msg);
        IMessage returnMethod = m_next.SyncProcessMessage(msg);
        PostProcess(msg, returnMethod);
        return returnMethod;
    }

    public IMessageCtrl AsyncProcessMessage(IMessage msg, IMessageSink replySink)
    {
        throw new InvalidOperationException();
    }
    #endregion //IMessageSink implementation

    #region Helper methods
    private void Preprocess(IMessage msg)
    {
        // We only want to process method calls
        if (!(msg is IMethodMessage)) return;

        IMethodMessage call = msg as IMethodMessage;
        Type type = Type.GetType(call.TypeName);
        m_typeAndName = type.Name + "." + call.MethodName;
        NLogging.Trace("PreProcessing: " + m_typeAndName + "(");

        // Loop through the [in] parameters
        for (int i = 0; i < call.ArgCount; ++i)
        {
            if (i > 0) Console.Write(", ");
            Console.Write(call.GetArgName(i) + " = " + call.GetArg(i));
        }
        NLogging.Trace(")");
    }

    private void PostProcess(IMessage msg, IMessage msgReturn)
    {
        // We only want to process method return calls
        if (!(msg is IMethodMessage) ||
            !(msgReturn is IMethodReturnMessage)) return;

        IMethodReturnMessage retMsg = (IMethodReturnMessage)msgReturn;
        NLogging.Trace("PostProcessing: ");
        Exception e = retMsg.Exception;
        if (e != null)
        {
            NLogging.Trace("Exception was thrown: " + e);
            return;
        }

        // Loop through all the [out] parameters
        NLogging.Trace(m_typeAndName + "(");
        if (retMsg.OutArgCount > 0)
        {
            NLogging.Trace("out parameters[");
            for (int i = 0; i < retMsg.OutArgCount; ++i)
            {
                if (i > 0) Console.Write(", ");
                Console.Write(retMsg.GetOutArgName(i) + " = " +
                              retMsg.GetOutArg(i));
            }
            NLogging.Trace("]");
        }
        if (retMsg.ReturnValue.GetType() != typeof(void))
            NLogging.Trace(" returned [" + retMsg.ReturnValue + "]");

        NLogging.Trace(")\n");
    }
    #endregion Helpers
}

public class TracingProperty : IContextProperty, IContributeObjectSink
{
    #region IContributeObjectSink implementation
    public IMessageSink GetObjectSink(MarshalByRefObject o, IMessageSink next)
    {
        return new TracingAspect(next);
    }
    #endregion // IContributeObjectSink implementation

    #region IContextProperty implementation
    public string Name
    {
        get
        {
            return "CallTracingProperty";
        }
    }
    public void Freeze(Context newContext)
    {
    }
    public bool IsNewContextOK(Context newCtx)
    {
        return true;
    }
    #endregion //IContextProperty implementation
}

[Conditional("DEBUG")]
[AttributeUsage(AttributeTargets.Class)]
public class TracingAttribute : ContextAttribute
{
    public TracingAttribute() : base("CallTracing") { }
    public override void GetPropertiesForNewContext(IConstructionCallMessage ccm)
    {
        ccm.ContextProperties.Add(new TracingProperty());
    }
}

using this tracingaspect I can log information about method only.If I want to log the method from which method was called.What can I do?


Solution

  • Set the tracing class access modifier to public

    public class TracingAspect : IMessageSink
    {
        public TracingAspect(IMessageSink next)
        {
            m_next = next;
        }
    

    Additional:

    Internal access modifier is the default access modifier for a class if none is specified and internal class is accessible only by classes within the same assembly.

    Project1
        > Class1
    Project2
        > Class2 (internal)
    

    Class2 of Project2 is only accessible by classes inside Project2 assembly. Hence, Class1 cannot create an instance / inherit Class2