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 🙂
4 Replies
Gael Fraiteur
Gael Fraiteur•15mo 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•15mo 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-QCCOP•15mo 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.
Whit
Whit•15mo 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