If I have a class:
class MyClass
{
IMyInterface _mi;
[MyAspectAttribute("_mi")]
bool _myValue;
// ...
}
Is there a way to create an aspect attribute MyAspectAttribute that intercepts getting and setting the value for (bool myValue) AND also imports the field that is specified in the attribute [MyAspectAttribute("_mi")] in this case _mi dynamically so I can use it in the aspect? (I want to call the interface before getting or setting the field in the aspect).
I know how to write the aspect I just don't know how to dynamically import the specified field (in this example _mi). All of the examples require that you know the exact field name to import (but I want the name passed to my aspect).
Thanks.
You can import the field dynamically by implementing IAdviceProvider.ProvideAdvices
method and returning ImportLocationAdviceInstance
for the field you want to import. The sample aspect below demonstrates this technique.
[PSerializable]
public class MyAspectAttribute : LocationLevelAspect, IAdviceProvider, IInstanceScopedAspect
{
private string _importedFieldName;
public MyAspectAttribute(string importedFieldName)
{
_importedFieldName = importedFieldName;
}
public ILocationBinding ImportedField;
public IEnumerable<AdviceInstance> ProvideAdvices(object targetElement)
{
var target = (LocationInfo) targetElement;
var importedField = target.DeclaringType
.GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)
.First(f => f.Name == this._importedFieldName);
yield return new ImportLocationAdviceInstance(
typeof(MyAspectAttribute).GetField("ImportedField"),
new LocationInfo(importedField));
}
[OnLocationGetValueAdvice, SelfPointcut]
public void OnGetValue(LocationInterceptionArgs args)
{
IMyInterface mi = (IMyInterface)this.ImportedField.GetValue(args.Instance);
mi.SomeMethod();
args.ProceedGetValue();
}
[OnLocationSetValueAdvice(Master = "OnGetValue"), SelfPointcut]
public void OnSetValue(LocationInterceptionArgs args)
{
IMyInterface mi = (IMyInterface) this.ImportedField.GetValue(args.Instance);
mi.SomeMethod();
args.ProceedSetValue();
}
public object CreateInstance(AdviceArgs adviceArgs)
{
return this.MemberwiseClone();
}
public void RuntimeInitializeInstance()
{
}
}