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.
Related
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.
Consider the case of StructLayout(LayoutKind.Explicit):
using System.Runtime.InteropServices;
[StructLayout(LayoutKind.Explicit)]
public struct UnionThingy
{
[FieldOffset(0x00)]
public short word;
[FieldOffset(0x00)]
public byte hiByte;
[FieldOffset(0x01)]
public byte lowByte;
public bool additionalField; // compile error!
}
Attempting to compile the above code results in the error CS0625
'UnionThingy.additionalField': instance field types marked with StructLayout(LayoutKind.Explicit) must have a FieldOffset attribute.
This seems an incredibly useful feature and I'm very curious how it is implemented.
I've read the MSDN tutorials on custom attributes, googled every related term I could think of, taken a look at the documentation for StructLayout and FieldOffset and even examined the metadata for those two attributes with "Go to definition..." in the VS code editor. I've been unable to find any clues on how the relationship between those two attributes is enforced.
If I want to do something similar:
[OptionalCustomAttribute]
public class DecoratedClass
{
[DetailsRequiredByOptionalCustomAttribute(2)] // compiler error if ommitted
public int SomeProperty {get; set;}
}
How would I go about it?
Edit: The question Force usage of custom attribute, proposed as a duplicate, asks how to force classes that inherit from a base class to include an attribute, not how to enforce members of a decorated class to include a certain attribute. Also, the answer provided is "it can't be done", whereas in this case is clearly has been done by the authors of the .net libraries. The question is simply how.
Some attributes contain information for the compiler. So naturally, there is explicit code in the compiler to interpret it and also error messages if this fails.
In our project, we have unit tests which load all types of our assemblies and check some attributes for consistency.
You can also make you application throw exceptions as early as possible (e.g. when starting up) in such cases. This is a simple solution if your application detects such errors anyway. It is important to throw early, otherwise you miss it until it went live...
I have decided to use Exceptions in my code to pass error handling around. I found myself duplicating code each time I wanted to create a new exception. These classes were nothing special and only contained a messaged. But I have come to rely on type safety when handing them. Is there a way to provide a new exception class type without having to re-implement the constructors?
[Serializable]
class MyNewException : MyBaseException
{
public MyNewException (String tMsg)
: base(tMsg)
{
}
public MyNewException (String tMsg, Exception tInnerEx)
: base(tMsg, tInnerEx)
{
}
}
The code above is duplicated many times over for each different type of exception I want to define.
Unfortunately, no, the constructors have to be provided since they are not inherited.
In addition, unless you are catching these specific exceptions and performing explicit processing when they occur, I would recommend having a generic exception that contains the additional information that you might need. However, this may not apply in your case.
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 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.