Why is .Net best practice to design custom attributes as sealed? - c#

I'm reading Pro C# 2010 and the .Net 4 Platform by Andrew Troelsen.
In Chapter 15 about Attributes exists a note:
Note: For security reasons, it is considered a .Net best practice to design all custom attributes as sealed.
The author doesn't explain why, can someone explain why?

CA1813: Avoid unsealed attributes:
The .NET Framework class library provides methods for retrieving
custom attributes. By default, these methods search the attribute
inheritance hierarchy; for example Attribute.GetCustomAttribute
searches for the specified attribute type, or any attribute type that
extends the specified attribute type. Sealing the attribute eliminates
the search through the inheritance hierarchy, and can improve
performance.
Ref: https://learn.microsoft.com/visualstudio/code-quality/ca1813-avoid-unsealed-attributes
Attributes are simply metadata discovered at runtime. As it is quoted, if someone else derives from your custom attribute class, by default .NET will find them too, which may imply a security risk if the derived attribute class is modifying the behavior of your original attribute in a way to you never intended to.
Even though performance is the prime reason to seal attribute classes, here is a formidable article dealing with its security side.

There is one more reason to seal attributes.
Consider the following attribute:
[AttributeUsageAttribute(AttributeTargets.Class, AllowMultiple = false)]
public class Attr1 : Attribute
{
}
Here you allow only single attribute decoration: AllowMultiple = false
Compiler won't allow this:
[Attr1]
[Attr1]
public class Foo
{
}
Later in your code you can safely call memberInfo.GetCustomAttribute() which will throw AmbiguousMatchException if more then one attribute of the given type was found.
Let's now inherit:
public class Attr2 : Attr1
{
}
Now compiler is silent.
[Attr1]
[Attr2]
public class Foo
{
}
So if later somebody inherits from your attribute and passes back to your code some entity marked with both attributes unexpected exception will be thrown.
Full example:
class Program
{
static void Main(params string[] args)
{
typeof(Foo).GetCustomAttribute<Attr1>();
}
[AttributeUsageAttribute(AttributeTargets.Class, AllowMultiple = false, Inherited = true)]
public class Attr1 : Attribute
{
}
public class Attr2 : Attr1
{
}
[Attr1]
[Attr2]
public class Foo
{
}
[Attr1]
public class Bar : Foo
{
}
}

Framework Design Guidelines: Conventions, Idioms, and Patterns for Reusable .NET Libraries just says:
DO seal custom attribute classes, if possible. This makes the look-up for the attribute faster.
I didn't see anything about security in that section, but #Teoman Soygul makes a good point. So I'd agree with Mr. Troelsen.

Related

How can an Attribute enforce inheritance?

In order to decorate a class with AttributeUsage, the decorated class must also inherit from Attribute.
Can I enforce a similar constraint with a custom attribute?
The AttributeUsageAttribute is apparently a core feature of the language, so this restriction is mandated by the C# specification:
A class that is decorated with the AttributeUsage attribute must derive from System.Attribute, either directly or indirectly. Otherwise, a compile-time error occurs.
That means there's no straightforward way of achieving such a restriction. You can write a custom static analyzer to throw warnings at erroneous usage, or see Anton Anpilogov's answer for a workaround.
The only way to do that is to use protected attribute, but in that case, you'll force users of your attribute to inherit from your attribute class.
abstract class CustomAttribute : Attribute {
[AttributeUsage(AttributeTargets.Class)]
protected sealed class MyTestAttribute : Attribute {}
}
[MyTest]
class DerivedFromYourCustomAttribute : CustomAttribute {
}
[MyTest]
class NotDerivedFromYourCustomAttribute {
}

Is it possible to extend an attribute?

In an app, I use different frameworks/technologies to serialize/deserialize objects. To ignore properties in the objects there are attributes like BsonIgnore or JsonIgnore.
[JsonIgnore]
[BsonIgnore]
public bool MyProperty
{
get;
set;
}
How can I create an attribute that extends from BsonIgnore and JsonIgnore so that I only need to specify one attribute for MyProperty?
The following does not work as an attribute has to extend System.Attribute.
[AttributeUsage(AttributeTargets.Class)]
public class MyIgnoreAttribute : BsonIgnore, JsonIgnore
{ ... }
-------------------------
[MyIgnore]
public bool MyProperty
{
get;
set;
}
C# doesn't support multiple-inheritance, and each of those types is sealed, so they couldn't be inherited from anyway. But there may be a different approach to do what you're trying to do.
If it is a predictable thing, for example: if something which has one attribute should always have the other attribute; you could use Aspect-Oriented Programming to inject the other attribute at compile time.
Your next question is going to be "how do I do that?", the answer to which will depend on what product you use.
Your question after that will be "which product should I use to do AOP?", which is off-topic, as shown here (hint: take a look at the linked page).
It's useless and impossible.
Look at source code of JsonIgnoreAttribute:
namespace Newtonsoft.Json
{
/// <summary>
/// Instructs the <see cref="T:Newtonsoft.Json.JsonSerializer" /> not to serialize the public field or public read/write property value.
/// </summary>
[AttributeUsage(AttributeTargets.Property | AttributeTargets.Field, AllowMultiple = false)]
public sealed class JsonIgnoreAttribute : Attribute
{
}
}
As you see, it does nothing.
In newtonsoft framework there is a code, that check that property has JsonIgnoreAttribute and do special work for that. It expects JsonIgnoreAttribute only.
Also, JsonIgnoreAttribute is sealed, you can't extend it.

Why is the C# SerializedAttribute is sealed?

I was trying to create an attribute that implies [Serializable] but I noticed that this SerializableAttribute class is sealed.
In Java it was possible to create an interface (say, MyInterface) that is inherited from Serializable interface and so all the subclasses of MyInterface would also be serializable, even its sub-sub classes would be so.
Let's say I am creating an ORM and I want customers to annotate their entity classes as [DatabaseEntity] but in order to make sure that entities are serializable, I also need to ask them to attribute their classes with extra [Serializable] which does not look quite compact and neat.
I am wondering why SerializableAttribute class is sealed and why has Inherited=false which implies that subclasses of serializable class will not be serializable unless it is explicitly stated. What motives are behind these design choices?
The SerializableAttribute is only used by the BinaryFormatter. If you are writing your own serialiser then don't worry about.
The sealed keyword is applied to the attribute not the class associated with the attribute. It is saying that the SerializableAttribute cannot be subclassed.
The BinaryFormatter uses an opt-in model. Any class (or subclass) must specify that it is serializable. This why the Inherited=false is used.
It's suggested best practice that all .Net attributes should be sealed, according to Microsoft:
The .NET Framework class library provides methods for retrieving custom attributes. By default, these methods search the attribute inheritance hierarchy; for example System.Attribute.GetCustomAttribute searches for the specified attribute type, or any attribute type that extends the specified attribute type. Sealing the attribute eliminates the search through the inheritance hierarchy, and can improve performance. [my emphasis]
So [Serializable] is sealed because it's quicker for .Net reflection to check the attributes. The cost is that you can't inherit and extend SerializableAttribute.
You can make your own un-sealed attributes if you want (you'll get code analysis warnings though).
This gets a little confusing with how attributes are used in inheritance for the classes that they apply to. It's probably best to use an example:
[Serializable]
public class A
{
public int SimpleSerialisableProperty { get; set;}
}
public class B : A
{
public C ComplexReferenceProperty { get; set; }
}
[Serializable]
public class D : A
{
public bool AnotherSerialisableProperty { get; set;}
}
You asked why SerializableAttribute.Inherited = false and this is why:
Class A is marked as [Serializable], and it is.
However class B inherits A and extends it with properties that are not serialisable. If .Net tries to serialise B it will encounter an error.
That Inherited = false tells .Net that just because A has been marked as [Serializable] not every class that inherits it will be serialisable too.
Now class D inherits A and is serialisable, so it gets its own [Serializable] attribute.
Finally, in terms of design attributes are a great way of extending behaviour (nice UI editors in property grids, etc). However they are terrible at enforcing it. If you need your customers to implement their entity classes in a particular way then an abstract base class or an interface is a much better way to go. If you make it an attribute then you're basically letting them know that [Serializable] is an option that you can handle either way.
Serialization is not a magic thing and you don't need any attribute to serialize an object. It is a process of writing your class' properties and fields to a stream (and attributes are only directives to serializers about how to behave while outputting an object).
See this over-simplified serializer code which totally ignores all attributes including NonSerializable
object obj = yourObject;
var props = obj.GetType()
.GetProperties()
.ToDictionary(p => p.Name, p => p.GetValue(obj, null));
string serializedText = String.Join("\n",
props.Select(kv => kv.Key + "=" + kv.Value ?? kv.Value.ToString()));
Above code, for example, would give
IsEmpty=False
X=3
Y=5
for object obj = new Point(3,5);
Deserialization process would be to read these values and set the properties back accordingly.
Put the [Serializable] attribute on top of the class you want serialized. Serialization is opt-in process. You have to manually do that for each class you want serialized. There are bunch of other keywords.

How do attribute classes work?

My searches keep turning up only guides explaining how to use and apply attributes to a class. I want to learn how to create my own attribute classes and the mechanics of how they work.
How are attribute classes instantiated? Are they instantiated when the class they are applied to is instantiated? Is one instantiated for each class instantiated that it is applied to? E.g. if I apply the SerializableAttribute class to a MyData class, and I instantiate 5 MyData instances, will there be 5 instances of the SerializbleAttribute class created behind the scenes? Or is there just one instance shared between all of them?
How do attribute class instances access the class they are associated with? How does a SerializableAttribute class access the class it is applied to so that it can serialize it's data? Does it have some sort of SerializableAttribute.ThisIsTheInstanceIAmAppliedTo property? :) Or does it work in the reverse direction that whenever I serialize something, the Serialize function I pass the MyClass instance to will reflectively go through the Attributes and find the SerialiableAttribute instance?
I haven't use attributes in my day-to-day work before, but I have read about them.
Also I have done some tests, to back up what I'll say here. If I'm wrong in any place - feel free to tell me this :)
From what I know, attributes are not acting as regular classes. They aren't instantiated when you create an object that they are applied to, not one static instance, not 1 per each instance of the object.
Neither do they access the class that they are applied to..
Instead they act like properties (attributes? :P ) of the class. Not like the .NET class properties, more like in the "one property of glass is transparency" kind of property. You can check which attributes are applied to a class from reflection, and then act on it accordingly. They are essentially metadata that is attached to the class definition, not the objects of that type.
You can try to get the list of attributes on a class, method, property, etc etc.. When you get the list of these attributes - this is where they will be instantiated. Then you can act on the data within these attributes.
E.g. the Linq tables, properties have attributes on them that define which table/column they refer to. But these classes don't use these attributes. Instead, the DataContext will check the attributes of these objects when it will convert linq expression trees to SQL code.
Now for some real examples.. I've ran these in LinqPad, so don't worry about the strange Dump() method. I've replaced it with Console.WriteLine to make the code easier to understand for the people who don't know about it :)
void Main()
{
Console.WriteLine("before class constructor");
var test = new TestClass();
Console.WriteLine("after class constructor");
var attrs = Attribute.GetCustomAttributes(test.GetType()).Dump();
foreach(var attr in attrs)
if (attr is TestClassAttribute)
Console.WriteLine(attr.ToString());
}
public class TestClassAttribute : Attribute
{
public TestClassAttribute()
{
DefaultDescription = "hello";
Console.WriteLine("I am here. I'm the attribute constructor!");
}
public String CustomDescription {get;set;}
public String DefaultDescription{get;set;}
public override String ToString()
{
return String.Format("Custom: {0}; Default: {1}", CustomDescription, DefaultDescription);
}
}
[Serializable]
[TestClass(CustomDescription="custm")]
public class TestClass
{
public int Foo {get;set;}
}
The console result of this method is:
before class constructor
after class constructor
I am here. I'm the attribute constructor!
Custom: custm; Default: hello
And the Attribute.GetCustomAttributes(test.GetType()) returns this array:
(the table shows all available columns for all entries.. So no, the Serializable attribute does not have these properties :) )
Got any more questions? Feel free to ask!
UPD:
I've seen you ask a question: why use them?
As an example I'll tell you about the XML-RPC.NET library.
You create your XML-RPC service class, with methods that will represent the xml-rpc methods. The main thing right now is: in XmlRpc the method names can have some special characters, like dots. So, you can have a flexlabs.ProcessTask() xml rpc method.
You would define this class as follows:
[XmlRpcMethod("flexlabs.ProcessTask")]
public int ProcessTask_MyCustomName_BecauseILikeIt();
This allows me to name the method in the way I like it, while still using the public name as it has to be.
Attributes are essentially meta data that can be attached to various pieces of your code. This meta data can then be interogate and affect the behaviour of certain opperations.
Attributes can be applied to almost every aspect of your code. For example, attributes can be associated at the Assembly level, like the AssemblyVersion and AssemblyFileVersion attributes, which govern the version numbers associated with the assembly.
[assembly: AssemblyVersion("1.0.0.0")]
[assembly: AssemblyFileVersion("1.0.0.0")]
Then the Serializable attribute for example can be applied to a type declaration to flag the type as supporting serialization. In fact this attribute has special meaning within the CLR and is actually stored as a special directive directly on the type in the IL, this is optimized to be stored as a bit flag which can be processed much more efficiently, there are a few attributes on this nature, which are known as pseudo custom attributes.
Still other attributes can be applied to methods, properties, fields, enums, return values etc. You can get an idea of the possible targets an attribute can be applied to by looking at this link
http://msdn.microsoft.com/en-us/library/system.attributetargets(VS.90).aspx
Further to this, you can define your own custom attributes which can then be applied to the applicable targets that your attributes are intended for. Then at runtime your code could reflect on the values contained in the custom attributes and take appropriate actions.
For a rather naive example, and this is just for the sake of example :)
You might want to write a persistence engine that will automatically map Classes to tables in your database and map the properties of the Class to table columns. You could start with defining two custom attributes
TableMappingAttribute
ColumnMappingAttribute
Which you can then apply to your classes, as an example we have a Person class
[TableMapping("People")]
public class Person
{
[ColumnMapping("fname")]
public string FirstName {get; set;}
[ColumnMapping("lname")]
public string LastName {get; set;}
}
When this compiles, other than the fact that the compiler emits the additional meta data defined by the custom attributes, little else is impacted. However you can now write a PersistanceManager that can dynamically inspect the attributes of an instance of the Person class and insert the data into the People table, mapping the data in the FirstName property to the fname column and the LastName property to the lname column.
As to your question regarding the instances of the attributes, the instance of the attribute is not created for each instance of your Class. All instances of People will share the same instance of the TableMappingAttribute and ColumnMappingAttributes. In fact, the attribute instances are only created when you actually query for the attributes the first time.
Yes they're instantiated with the parameters you give it.
The attribute does not "access" the class. The attribute is attached to the class' / property's attribute list in the reflection data.
[Serializable]
public class MyFancyClass
{ ... }
// Somewhere Else:
public void function()
{
Type t = typeof(MyFancyClass);
var attributes = t.GetCustomAttributes(true);
if (attributes.Count(p => p is SerializableAttribute) > 0)
{
// This class is serializable, let's do something with it!
}
}
Think of attributes are post-its that are attached to the classes or method definitions (embedded in the assembly metadata).
You can then have a processor/runner/inspector module that accepts these types by reflecting, looks for these post-its and handles them differently. This is called declarative programming. You declare some behavior instead of writing code for them in the type.
Serializable attribute on a type declares that it is built to be serialized. The XmlSerializer can then accept an object of this class and do the needful. You mark the methods that need to be serialized/hidden with the right post-its.
another example would the NUnit. The NUnit runner looks at the [TestFixture] attributes all classes defined in the target assembly to identify test classes. It then looks for methods marked with [Test] attribute to identify the tests, which it then runs and displays the results.
You may want to run through this tutorial at MSDN which has most of your questions answered along with an example at the end. Although they could have extracted a method called
Audit(Type anyType); instead of duplicating that code. The example 'prints information' by inspecting attributes.. but you could do anything in the same vein.
If you take an eye out this downloadable open source code LINQ to Active Directory (CodePlex), you might find interesting the mechanism of the Attributes.cs file where Bart De Smet has written all of his attributes classes definitions. I have learned attributes there.
In short, you may specialize the Attribute class and code some specialized properties for your needs.
public class MyOwnAttributeClass : Attribute {
public MyOwnAttributeClass() {
}
public MyOwnAttributeClass(string myName) {
MyName = myName;
}
public string MyName { get; set; }
}
and then, you may use it wherever MyOwnAttributeClass gets useful. It might either be over a class definition or a property definition.
[MyOwnAttributeClass("MyCustomerName")]
public class Customer {
[MyOwnAttributeClass("MyCustomerNameProperty")]
public string CustomerName { get; set; }
}
Then, you can get it through reflection like so:
Attribute[] attributes = typeof(Customer).GetCustomAttribute(typeof(MyOwnAttributeClass));
Consider that the attribute you put between square brackets is always the constructor of your attribute. So, if you want to have a parameterized attribute, you need to code your constructor as such.
This code is provided as is, and may not compile. Its purpose is to give you an idea on how it works.
Indeed, you generally want to have a different attribute class for a class than for a property.
Hope this helps!
Not much time to give you a fuller answer, but you can find the Attributes that have been applied to a value using Reflection. As for creating them, you inherit from the Attribute Class and work from there - and the values that you supply with an attribute are passed to the Attribute class's constructor.
It's been a while, as you might be able to tell...
Martin

c# hide Attribute in derived Class

I have a base class with an attribute and I want to hide it in a derived class. Is there any way to do this other than using reflection?
[Authorize(Roles = "User,Admin,Customs")]
public abstract class ApplicationController : Controller
{
}
// hide the Authorize attribute
public class ErrorController : ApplicationController
{
}
You could override the AuthorizeAttribute with your own class and specify it to not be inherited.
[AttributeUsage(AttributeTargets.Class, Inherited=false)]
public class NonInheritedAuthorizeAttribute : AuthorizeAttribute
{
// Constructors, etc.
}
Now you can specify which class to use, as long as you own ApplicationController.
Removing features inherited from a base class violates the Liskov Substitution Principle. Breaking inheritance in this way usually rears its ugly head with unintended and unexpected consequences—after it's too late to change the root problem.
So even if there is a way, I'll answer that you shouldn't use it the vast majority of the time. Alternatives to inheritance may apply, such as containment (has-a instead of inheritance's is-a) or refactoring the base into a separate interface which both can then implement; or even combine both of these.
If it was a method/prop, you could re-declare (new) the member without the offending attribute. I don't know of a way with class-level attributes.
public new SomeType Foo() { return base.Foo(); }
Depends a bit on what you mean by 'Hide'. You should be able to revoke the authorization like this:
// hide the Authorize attribute
[Authorize(Roles = "")]
public class ErrorController : ApplicationController
{
}
You can specify the 'AttributeUage' attribute on your Attribute class, like this:
[AttributeUsage(AttributeTargets.Class, Inherited=false)]
public class AuthorizeAttribute : Attribute
{
}
Then, classes that derive from the class where you've applied the attribute, will not inherit the attribute.
Ow, now I realize that the Authorize attribute is not a custom attribute.

Categories

Resources