Giving Aspects Metadata ?

I've only just started messing with MetaLama and going thru the documentation and videos but I was wondering if its possible to give an attribute extra metadata to send based on the place its invoked for example
public class HookFunctionAndPrint : OverrideMethodAspect
{
public override dynamic? OverrideMethod()
{
//hooks on method start
var functionName = meta.Target.Method.Name;
Console.WriteLine($"Hooked on {functionName} method start");
try
{
// Let the method do its own thing.
return meta.Proceed();
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
Console.WriteLine(ex.StackTrace);
return null;
}
finally
{
Console.WriteLine($"Hooked on {functionName} method end");
}
}
}
public class HookFunctionAndPrint : OverrideMethodAspect
{
public override dynamic? OverrideMethod()
{
//hooks on method start
var functionName = meta.Target.Method.Name;
Console.WriteLine($"Hooked on {functionName} method start");
try
{
// Let the method do its own thing.
return meta.Proceed();
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
Console.WriteLine(ex.StackTrace);
return null;
}
finally
{
Console.WriteLine($"Hooked on {functionName} method end");
}
}
}
but what if I wanted extra metadata such as stuff you get along with MEF plugins if you are familiar with that but something lets say a string to set a logging verbosity.
public class HookFunctionAndPrint : OverrideMethodAspect
{
public override dynamic? OverrideMethod()
{
//hooks on method start
var functionName = meta.Target.Method.Name;
Console.WriteLine($"Hooked on {functionName} method start");
try
{
// logging level here would be a defined name when the attribute is set
if(meta.Metadata.loggingLevel == "Verbose")
{
Console.WriteLine($"verbose logging enabled for {functionName}");
}
else if(meta.Metadata.loggingLevel == "info")
{
Console.WriteLine($"info only logging enabled for {functionName}");
}
// Let the method do its own thing.
return meta.Proceed();
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
Console.WriteLine(ex.StackTrace);
return null;
}
finally
{
Console.WriteLine($"Hooked on {functionName} method end");
}
}
}
public class HookFunctionAndPrint : OverrideMethodAspect
{
public override dynamic? OverrideMethod()
{
//hooks on method start
var functionName = meta.Target.Method.Name;
Console.WriteLine($"Hooked on {functionName} method start");
try
{
// logging level here would be a defined name when the attribute is set
if(meta.Metadata.loggingLevel == "Verbose")
{
Console.WriteLine($"verbose logging enabled for {functionName}");
}
else if(meta.Metadata.loggingLevel == "info")
{
Console.WriteLine($"info only logging enabled for {functionName}");
}
// Let the method do its own thing.
return meta.Proceed();
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
Console.WriteLine(ex.StackTrace);
return null;
}
finally
{
Console.WriteLine($"Hooked on {functionName} method end");
}
}
}
then when you give the attribute to the function you do something like
[HookFunctionAndPrint]
[MetaLamaMetadata("Logging", "Verbose")]
static void Main(string[] args)
{
}
[HookFunctionAndPrint]
[MetaLamaMetadata("Logging", "Verbose")]
static void Main(string[] args)
{
}
I dont know if something like this alrady exists and I just missed it in the docs or if this would be a feature request. Also currently on the free license if this is a premium feature 🙂
Gael Fraiteur
Gael Fraiteur•231d ago
This feature is called "call-site aspects" and is currently unsupported. The closest way you can implement this is to use the .NET StackFrame class to capture the caller.
Petr Onderka
Petr Onderka•229d ago
If I understand you correctly, the simplest way to do this is to add the data to the aspect class:
public class HookFunctionAndPrint : OverrideMethodAspect
{
public string? LoggingLevel { get; }

public HookFunctionAndPrint(string? loggingLevel = null)
{
LoggingLevel = loggingLevel;
}

public override dynamic? OverrideMethod()
{
if(LoggingLevel == "Verbose")
{
Console.WriteLine("verbose logging enabled");
}
...
}
}
}

class Program
{
[HookFunctionAndPrint("Verbose")]
static void Main()
{
}
}
public class HookFunctionAndPrint : OverrideMethodAspect
{
public string? LoggingLevel { get; }

public HookFunctionAndPrint(string? loggingLevel = null)
{
LoggingLevel = loggingLevel;
}

public override dynamic? OverrideMethod()
{
if(LoggingLevel == "Verbose")
{
Console.WriteLine("verbose logging enabled");
}
...
}
}
}

class Program
{
[HookFunctionAndPrint("Verbose")]
static void Main()
{
}
}
If you want to keep it on another attribute, you can, by reading the attribute from your aspect:
public class HookFunctionAndPrint : OverrideMethodAspect
{
public override dynamic? OverrideMethod()
{
var loggingLevel = meta.Target.Declaration.Attributes.OfAttributeType(typeof(MetaLamaMetadataAttribute))
.SingleOrDefault(a => a.ConstructorArguments[0].Value is "Logging")
?.ConstructorArguments[1].Value;

if(loggingLevel is "Verbose")
{
Console.WriteLine("verbose logging enabled");
}

...
}
}

class C
{
[HookFunctionAndPrint]
[MetaLamaMetadata("Logging", "Verbose")]
static void Main()
{
}
}

[AttributeUsage(AttributeTargets.All, AllowMultiple = true)]
internal class MetaLamaMetadataAttribute : Attribute
{
public string Key { get; }
public string Value { get; }

public MetaLamaMetadataAttribute(string key, string value)
{
Key = key;
Value = value;
}
}
public class HookFunctionAndPrint : OverrideMethodAspect
{
public override dynamic? OverrideMethod()
{
var loggingLevel = meta.Target.Declaration.Attributes.OfAttributeType(typeof(MetaLamaMetadataAttribute))
.SingleOrDefault(a => a.ConstructorArguments[0].Value is "Logging")
?.ConstructorArguments[1].Value;

if(loggingLevel is "Verbose")
{
Console.WriteLine("verbose logging enabled");
}

...
}
}

class C
{
[HookFunctionAndPrint]
[MetaLamaMetadata("Logging", "Verbose")]
static void Main()
{
}
}

[AttributeUsage(AttributeTargets.All, AllowMultiple = true)]
internal class MetaLamaMetadataAttribute : Attribute
{
public string Key { get; }
public string Value { get; }

public MetaLamaMetadataAttribute(string key, string value)
{
Key = key;
Value = value;
}
}
Drago-QCC
Drago-QCC•229d ago
Oooh that's an interesting idea, i didn't even think about adding the properties straight into the aspect I'll mess around with that, thanks.
Xaniff
Xaniff•226d ago
I do this in an aspect I've written. Remember that the aspects themselves don't really exist at runtime - they're only a compile-time thing, so any metadata you're passing around about anything is only valid (unless you persist it somewhere) while it's building your project. Because I do an analysis of how the properties are used and then inject all manner of things based on that analysis, I just store a Dictionary<string, INamedType> that I pass around between methods in the aspect.
Want results from more Discord servers?
Add your server
More Posts
Unable to get aspect testing to workI've got a very simple class set up to apply a logging aspect to so I can get the hang down of testiHow to debug a "Cannot preview the transformed code: unknown error"?I've got an aspect that's building without error and a target project that's applying the aspect thaWarn on ineligibility instead of throwingI've got two conditions in my BuildEligibility for a method override aspect: If the target type is aReferencing value assigned to variable in statement builder within another statementGiven a statement that does something like: ```cs var expr = new ExpressionBuilder(); expr.AppendVerSpecifying generic constraints of compile-time introduced typeI have a TypeAspect that has three attribute arguments when applied to a type. One of these is a `TyStep-through aspect-debuggingI'm sure I've asked this before, but I cannot find the thread in which it was answered (if I actuallCodeLens HelpMetalama is configured in CodeLens, and I have an aspect that has been applied. I am able to right-How to apply an attribute to a method introduced by another aspect?I have an aspect that has a dependency on another aspect. However, I'd like for downstream projects Advising the addition of code commentsUsing Metalama Is there a way to advise adding code comments? For example, when I advise a method Set eligibility to not run against (built-in) methods of record classes or structsI've figured out how to set up an `If` statement for the record types, but I cannot figure out how tHow to specify an IMethod as the callback for an event?I'd like to specify an introduced method on a TypeAspect as the callback for an event handler. 1) WCreate NuGet with MetalamaWith source generators I have to add some MSBuild configuration, but with Metalama it seems I don't