Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature: Attribute Multicasting #218

Closed
APEX-JOAQUIN-ROVIRA opened this issue Jun 7, 2023 · 1 comment
Closed

Feature: Attribute Multicasting #218

APEX-JOAQUIN-ROVIRA opened this issue Jun 7, 2023 · 1 comment

Comments

@APEX-JOAQUIN-ROVIRA
Copy link

APEX-JOAQUIN-ROVIRA commented Jun 7, 2023

First of all, congratulations on the amazing project. Works flawlessly as an open-source alternative to PostSharp. However, there is one feature that I am deeply missing. It's the ability to apply an aspect to multiple classes in one broad stroke based on some condition.

PostSharp has MulticastAttribute which does exactly this. The condition can typically be a Namespace regex.

[assembly: MyAspect(AttributeTargetTypes = "Some.Namespace.Path.*")]

I found a very similar (closed) issue #143. I have tried Interface Triggers as described, however they do no "bubble up" the inheritance chain. This means it's essentially an alternative syntax to the normal attribute definitions. Using the following code as example.

[Aspect(Scope.PerInstance)]
public class MyAspect
{
    [Advice(Kind.Before, Targets = Target.Method)]
    public void LogEnter() { Console.WriteLine($"Method call detected!"); }
}

[Injection(typeof(MyAspect))]
public class IExample { }

public class A : IExample {
  void Something() { } // Calls LogEnter()
}

public class B : A {
  void Another() { } // Does not call LogEnter()
}

This works as expected as defined in the docs and examples. However, what I am looking for is an alternative that would allow for B.Another() to be automatically injected with MyAspect.

In the closed issue you comment about possible solutions that would allow for exactly this behaviour without relying on some kind of CompileTimeValidate method.

I was thinking about additional Propagation options to allows only certain types, like PropagateToTypes=[typeof(IRequiresPermissionCheck)]. This should work for methods too, restricting by return type. But it won't throw compile time error, it will just ignore incorrect attribute assignment attempts.

So for restricting targets I think it is possible (won't break anything) to add new field to InjectionAttribute - RestrictToTypes=[typeof(IRequiresPermissionCheck)], combining that with your regular AttributeUsage(Class) might fulfill your requirements.

Please feel free to contribute)

I am by no means an expert, or even slightly knowledgeable on the topic of compile-time assembly transformations. If not, I would send a PR myself. Would it be possible to add a feature that allowed for such broad but controlled application of an aspect.

This could be either through the use of multicast attributes or through interface inheritance. Perhaps some other solution that would enable more control over which aspects are applied to which classes without having to manually include the atribute or the interface on each one.

[assembly: MyAttribute]

[Injection(typeof(MyAspect), RestrictToTypes=[typeof(IExample)])]
public class MyAttribute { }

[Aspect(Scope.PerInstance)]
public class MyAspect
{
    [Advice(Kind.Before, Targets = Target.Method)]
    public void LogEnter() { Console.WriteLine($"Method call detected!"); }
}

public class IExample { }

public class A : IExample {
  void Something() { } // Calls LogEnter()
}

public class B : A {
  void Another() { } // Calls LogEnter()
}
@APEX-JOAQUIN-ROVIRA
Copy link
Author

Just realized this is a copy of #197. Closing this one.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

1 participant