I'm trying to write a custom attribute that I can apply to methods that will prevent the method from being called when Transaction.Current is null. I currently have a basic attribute class that throws an exception if that item is null. Here it is:
[AttributeUsage(AttributeTargets.Method)]
public class RequiresTransactionAttribute : System.Attribute
{
public RequiresTransactionAttribute()
{
if (Transaction.Current == null)
{
throw new Exception("requires transaction");
}
}
}
The problem is that this does not cause method calls to fail in my tests.
I've read that these attributes are converted to meta data and so this constructor is never executed because it's optimized out unless I specifically use reflection to cause the attribute to be executed.
Is it possible to prevent a method from being called based on such a requirement as mine using attribute approach, or perhaps some other better method?
With very few exceptions (attributes with inbuilt behaviour by the runtime, where the JIT is looking for them - like [MethodImpl(...)] or code-access-security attributes), attributes are completely inert - they exist purely as metadata. They aren't even instantiated as objects unless you use reflection to ask it to do so.
So no: you can't influence runtime behaviour like this unless you are using a framework that goes out of the way to look for attributes, instantiate them, and treat them as runnable code via methods that the framework itself checks. ASP.NET MVC would be an example of a framework that does this.
The other option is an IL rewriter such as post-sharp, where attributes are a popular hook for injecting additional code during weave.
Related
I have a pretty standard .net core 2 WebApi project. I want to add an attribute on a method that will kick off when the action is called.
In the pseudo code below whenever someone posts to the foo action, I'd like to log the body of the POST. To that end I add the [LogBody] attribute. But I don't know how to actually kick off a method in the attribute.
class SomeController: Controller {
[HttpPost]
[LogBody]
public void foo([FromBody] SomeObj obj) {
return View(obj);
}
}
class LogBodyAttribute: Attribute {
void LogIt() {
string methodName = getMethodName();
string body = new StreamReader(Request.Body, Encoding.UTF8).ReadToEnd();
SaveData(methodName, body);
}
}
P.S. I know I can do this with PostSharp, but I'd rather not.
It can be done, but it's not easy - and the immediate answer to your question involves reflection and code injection stuff. Here is an SO question that might help you do what you want: C# Attribute to trigger an event on invoking a method
The attributes provide a static meta-data that is included into the compiled code. This information can be queried at run-time and used to perform logic; however, the attribute by itself cannot trigger an action.
Given an object, you can get the attribute like this:
Type type = controller.GetType();
var myAttribute = type
.GetMethod(methodName)
.GetCustomAttributes(true)
.OfType<MyAttribute>()
.FirstOrDefault();
The Boolean argument to GetCustomAttributes indicates whether inherited attributes must be returned.
Maybe what you are looking for is Aspect-oriented programming AOP. This allows you to inject code into methods and properties in a post compilation process. Attributes can be used to include or exclude methods. There are different AOP products available for C#.
Yet another approach is to use the Decorator pattern. A decorator is a wrapper class providing the same API than the wrapped class and allows to add behavior to the methods and properties of the wrappee. Used together with an inversion of control (IoC) Container or with the Factory method pattern, behavior can automatically be injected.
It is valid (ie. it compiles and runs) to put an attribute on the generic parameter for a class or a method:
public class MyClass<[My] T>
{
private void MyMethod<[My] T>()
{}
}
public class MyAttribute : Attribute
{}
I've never seen this used, and am struggling to come up with a reason as to why you would want to.
Is it just a quirk/side-effect of the language specification, or is there a valid/useful reason to put an attribute in this position?
For the same reason attributes are useful on any construct; they supply meta-data that can be used by Reflection or other post-processors to do various things. For instance, you might have an AOP system that uses an attribute on a type argument to apply certain run-time constraints that otherwise could not be expressed. I'm not sure if there are any systems that actually use these attributes to do anything, but there's no reason to disallow them as metadata.
I'm sure some AOP nut will find a valid reason to decorate generic parameters with attributes. I certainly can't think of any. Try this:
typeof(MyClass<>).GetGenericArguments().GetCustomAttributes().OfType<MyAttribute>();
If this Enumerable has any elements, then it is possible to access the attribute you placed on the class's generic parameter. If not, then you can't and thus having data you'd expect to access from any other class in your codebase is pointless. HOWEVER, they can still have code that runs when instantiated, and they're instantiated by the runtime when the generic class comes into scope, allowing you to perform aspect-oriented logic in the attribute itself. Exactly what that would be, and how it would be any different than decorating the generic class or method directly, is left as an exercise to people who worship AOP far more than I do.
I've found that attributes in C# seem to be lazily instantiated.
[A(123)]
class A : Attribute
{
public A(int b)
{
GetType().GetCustomAttributes(true);
}
}
In this example, creating a new A instance causes a StackOverflowException, but if I remove the call to GetCustomAttributes(), then execution carries on normally.
Why is this? It makes more sense to me that attributes are properly initialized when the class they decorate is.
Why the runtime would need to instantiate all attributes on class before you requested them? It is like asking why runtime does not create an instance of my class in advance, just in case I want to use it later.
Attributes are meta data on class, they do not affect the class work in any way. Only the code the requests the attribute care about it, no one else is not. So the current behavior does make sense.
Since attribute functionality is only ever executed by code that is actively looking for the attribute in question, it's wasteful for the runtime to instantiate attributes until they are first used - indeed, during the lifetime of a program, attributes may never be inspected.
Attributes are "information" associated to a type, and not to an instance.
There is no reason why they should be instantiated when you create an object of the type they are attached to, instead you can see them when you're inspecting the type itself.
I've created a simple Attribute:
[AttributeUsage(AttributeTargets.Method)]
public class InitAttribute : System.Attribute
{
public InitAttribute()
{
Console.WriteLine("Works!");
}
}
and I apply it to a simple method:
static class Logger
{
public static string _severity;
public static void Init(string severity)
{
_severity = severity;
}
[Init()]
public static void p()
{
Console.WriteLine(_severity);
}
}
What is going on is pretty streight-forward. Only, I expect the attribute to perform an action (printing Works!), but this does not happen.
Addictionally, printing "Works!" is of course just for debugging purposes: I'd like to access the instance's property _severity (to check if is != null, for example), but everything I keep reading about attributes (that are pretty new to me) is about accessing the class' methods or properties and so on via reflection. Once I've evaluated _severity, how can I modify the behavior of the decorated method (in this case, rise an exception "Logger is not initialized" and do not execute it)?
Any help appreciated.
If you need to perform an action as control enters a method, you should look at aspect-oriented programming and frameworks such as PostSharp. Attributes are not designed to perform anything by themselves. They are just a bunch of data (or metadata if you will) attached to stuff in IL assemblies that can be queried at runtime.
Attributes only allow decoration of types and members, but the attribute itself cannot acces the decorated object. You will have to use the constructor parameters of the attribute to pass in any data you require to work with within the attribute.
If you wish to use attributes to automatically alter the behaviour of their target objects, you will have to look at AOP solutions like PostSharp.
The attribute is never actually instantiated and so its constructor is never called. The attribute remains as meta-data until you use reflection to retrieve it. As has been mentioned previously what you are after is an Aspect Oriented Programming tool. PostSharp works by altering the assembly as a post-build step. If you are using the Castle Windsor or Unity Inversion of Control Containers they both offer AOP capabilities as well.
while writing a custom attribute in C# i was wondering if there are any guidelines or best practices regarding exceptions in attributes.
Should the attribute check the given parameters for validity? Or is this the task of the user of the property?
In a simple test I did the exception was not thrown until i used GetCustomAttributes on a type with an exception throwing attribute.
I just think it's a bit awkward to get an exception from an Attribute only when explicitly asking for them.
Example Attribute with exception:
[AttributeUsage(AttributeTargets.Interface, AllowMultiple = false, Inherited = false)]
sealed public class MyAttribute : Attribute
{
public string SomeValue { get; private set; }
public MyAttribute(string someValue)
{
if(string.IsNullOrEmpty(someValue))
{
throw new ArgumentNullException("path");
}
if(!someOtherCheck(someValue))
{
throw MyAttributeException("An other error occured");
}
SomeValue = someValue;
}
}
Attributes are only actually constructed when you use reflection, so that's the only time you can throw an exception. I can't remember ever using an attribute and having it throw an exception though. Attributes usually provide data rather than real behaviour - I'd expect the code which uses the attribute to provide any validation. I know this isn't like normal encapsulation, but it's the way it tends to be in my experience.
With a few exceptions with compiler-sepcific meaning (such as [PrincipalPermission] etc.) attributes can't interact directly with code without being asked to. However, if you use the AOP (Aspect Oriented Programming) tool "PostSharp", your aspect attributes can add behaviour to your class. Not simple, but it's a very useful trick sometimes.
We have some reasonably complex Attributes in our project, so we include validation of inputs. For example, as part of our I18N and L10N work, we have attributes that perform resource lookups (much like the attributes in the framework that are used to localise Category and Description strings for properties in the designers). These custom attributes have to have some validation in order for them to work.
The simple attributes we have use no validation because we'd rather the consuming code failed, indicating the location of the error.
So, in conclusion, it really depends on the complexity of the attribute; if it is instantiated with one kind of data but expected to provide another (such as in resource lookups), it should contain validation, otherwise, it probably shouldn't.