Reputation: 119
I wrote an abstract class that uses reflection to find fields marked with an Attribute in the constructor, like this:
[AttributeUsage(AttributeTargets.Field)]
public class TrackedField : Attribute {}
public class ATrackedObject {
public ATrackedObject() {
Type objType = this.GetType();
foreach(FieldInfo f in objType.GetFields()) {
if(f.IsDefined(typeof(TrackedField)), false)) {
//Add field to list to keep tabs on periodically
}
}
}
}
What I would like to do, is:
I have seen a number of SE threads discussing how to do this, and all of the answers relied on being able to use a third party library - however, none of the questions seemed to match my use case exactly - I can ensure 100% that every object that needs to have methods tracked will inherit from the class that does the tracking.
I don't know for sure this is possible, but I am wondering since IoC/AOP libraries like PostSharp and others exist, surely they must operate by some kind of mechanism - I assume Reflection.Emit plays a part - but what, and how?
Here are some similar questions, which did not have what seemed to me to be answers to my specific scenario, or relied on third party libraries:
custom-attribute-to-process-info-before-a-method-is-called
how-do-i-intercept-a-method-call-in-c (this was helpful, but missing the crucial component of how to actually inject code
Is there a way to make this technique (Attribute -> Base Class Constructor -> Reflection -> Method Interception) viable?
Upvotes: 2
Views: 3695
Reputation: 1372
Could something like this work for what you need?
[AttributeUsage(AttributeTargets.Field)]
public class TrackedField : Attribute { }
public class ATrackedObject
{
public ATrackedObject()
{
Type objType = this.GetType();
foreach (FieldInfo f in objType.GetFields())
{
if (f.IsDefined(typeof(TrackedField), false)) {
if (f.FieldType == typeof(Action))
{
var currentValue = f.GetValue(this) as Action;
Action newValue = () =>
{
Console.WriteLine($"Tracking {f.Name}");
currentValue.Invoke();
};
f.SetValue(this, newValue);
}
}
}
}
[TrackedField]
public Action SomeMethod = () => Console.WriteLine("Some Method Called");
}
this is done with a simple Action
property but it could be extended to use Func<>
edit: forgot to include usage and output.
usage:
static void Main(string[] args)
{
var obj = new ATrackedObject();
obj.SomeMethod();
Console.Read();
}
output:
Tracking SomeMethod
Some Method Called
Upvotes: 4