In my project, I need to use custom attribute on all assemblies. This
attribute will implement some non-functional code and I want to use it on
assembly scope(Attribute Targets is Assembly).
I add code "[assembly: CallTracing()]" in file AssemblyInfo.cs . But it
seemed that it didn't work. I don't know why.
CODE AS BELOW:
TestAttribute.c s++++++++++++++ +++++++++++++++ +++++++++++++++ +++++++++++++++ Â*++++++++++
using System;
using System.Reflecti on;
using System.Runtime. Remoting.Messag ing;
using System.Runtime. Remoting.Contex ts;
using System.Runtime. Remoting.Activa tion;
namespace AOP.Experiment
{
internal class CallTracingAspe ct : IMessageSink
{
private IMessageSink m_next;
private String m_typeAndName ;
internal CallTracingAspe ct(IMessageSink next)
{
// Cache the next sink in the chain
m_next = next;
}
public IMessageSink NextSink
{
get
{
return m_next;
}
}
public IMessage SyncProcessMess age(IMessage msg)
{
Preprocess(msg) ;
IMessage returnMethod =
m_next.SyncProc essMessage(msg) ;
PostProcess(msg , returnMethod);
return returnMethod;
}
public IMessageCtrl AsyncProcessMes sage(IMessage msg,
IMessageSink
replySink)
{
throw new InvalidOperatio nException() ;
}
public static string ContextName
{
get
{
return "CallContex t" ;
}
}
private void Preprocess(IMes sage msg)
{
if (!(msg is IMethodMessage) ) return;
IMethodMessage call = msg as IMethodMessage;
Type t = Type.GetType(ca ll.TypeName) ;
m_typeAndName = t.Name + "." + call.MethodName ;
Console.Write(" calltrace PreProcessing: " +
m_typeAndName + "(");
for (int i = 0; i < call.ArgCount; ++i)
{
if (i > 0) Console.Write(" , ");
Console.Write(c all.GetArgName( i) + "= " +
call.GetArg(i)) ;
}
Console.WriteLi ne(")");
// set us up in the callContext
call.LogicalCal lContext.SetDat a(ContextName, this);
}
private void PostProcess(IMe ssage msg, IMessage msgReturn)
{
// We only want to process method return calls
if (!(msg is IMethodMessage) ||
!(msgReturn is IMethodReturnMe ssage)) return;
IMethodReturnMe ssage retMsg =
(IMethodReturnM essage)msgRetur n;
Console.Write(" calltrace PostProcessing: ");
Exception e = retMsg.Exceptio n;
if (e != null)
{
Console.WriteLi ne("Exception was thrown: " +
e);
return;
}
// Loop through all the [out] parameters
Console.Write(m _typeAndName + "(");
if (retMsg.OutArgC ount > 0)
{
Console.Write(" out parameters[");
for (int i = 0; i < retMsg.OutArgCo unt; ++i )
{
if (i > 0) Console.Write(" , ");
Console.Write(r etMsg.GetOutArg Name(i) + "= " +
retMsg.GetOutAr g(i));
}
Console.Write("]");
}
if (retMsg.ReturnV alue.GetType() != typeof(void))
Console.Write(" returned [" +
retMsg.ReturnVa lue + "]");
Console.WriteLi ne(")");
}
}
public class CallTracingProp erty : IContextPropert y,
IContributeServ erContextSink
{
public IMessageSink GetServerContex tSink(IMessageS ink next)
{
Console.WriteLi ne("***In CallTracingProp erty's
GetObjectSink** *");
Console.WriteLi ne("Next Message Sink is " +
next.GetType()) ;
return new CallTracingAspe ct(next);
}
public bool IsNewContextOK( Context newCtx )
{
return true ;
}
public void Freeze(Context newContext)
{
}
public string Name
{
get
{
return "CallTracingPro perty";
}
}
}
[AttributeUsage( AttributeTarget s.Assembly)]
public class CallTracingAttr ibute : ContextAttribut e
{
public CallTracingAttr ibute() : base("CallTraci ng") {}
public override void
GetPropertiesFo rNewContext(ICo nstructionCallM essage ccm)
{
ccm.ContextProp erties.Add(new CallTracingProp erty());
Console.WriteLi ne("CallTracing Attribute has been
created for new
context");
}
}
}
TestClass.cs+++ +++++++++++++++ +++++++++++++++ +++++++++++++++ +
using System;
namespace AOP.Experiment
{
public class cTestClass:Cont extBoundObject
{
public cTestClass()
{
Console.WriteLi ne("TestClass ctor()");
}
public override string ToString()
{
return "Test Class";
}
}
}
TestClass.csçš„ AssemblyInfo.cs +++++++++++++++ +++++++++++++++ +++++++
using System.Reflecti on;
using System.Runtime. CompilerService s;
using AOP.Experiment;
[assembly: CallTracing()]
[assembly: AssemblyTitle(" ")]
[assembly: AssemblyDescrip tion("")]
[assembly: AssemblyConfigu ration("")]
[assembly: AssemblyCompany ("")]
[assembly: AssemblyProduct ("")]
[assembly: AssemblyCopyrig ht("")]
[assembly: AssemblyTradema rk("")]
[assembly: AssemblyCulture ("")]
[assembly: AssemblyVersion ("1.0.*")]
[assembly: AssemblyDelaySi gn(false)]
[assembly: AssemblyKeyFile ("")]
[assembly: AssemblyKeyName ("")]
TestManager.cs+ +++++++++++++++ +++++++++++++++ +++++++++++++++ +++++++++++++++ Â*++++
using System;
using System.Reflecti on;
namespace AOP.Experiment
{
class cTestManager
{
[STAThread]
static void Main(string[] args)
{
Assembly TestAssembly;
cTestClass TestClass;
try
{
Console.WriteLi ne("dd");
TestAssembly =
Assembly.LoadFr om("E:\\DR\\Mod ule\\Debug\\Tes tClass.dll");
Console.WriteLi ne(TestAssembly .GetName().ToSt ring());
TestClass =
(cTestClass)Tes tAssembly.Creat eInstance("AOP. Experiment.cTes tClass");
Console.WriteLi ne(TestClass.To String());
}
catch(Exception e)
{
Console.WriteLi ne(e.ToString() );
}
Console.ReadLin e();
}
}
-----------------------------------------------------------------------------------
The result what I supposed is , after I run cTestManager.Ma in(),
Preprocess() in TestAttribute.c s should run before
TestAssembly.Cr eateInstance("A OP.Experiment.c TestClass");
But the result was not what I expected, Preprocess() wasn't executed. If I
apply this attribute on Class scope, Preprocess() would executed. I don't
know why.