Login | Register   
Twitter
RSS Feed
Download our iPhone app
TODAY'S HEADLINES  |   ARTICLE ARCHIVE  |   FORUMS  |   TIP BANK
Browse DevX
Sign up for e-mail newsletters from DevX


advertisement
 

Get Personal with C# Custom Attributes : Page 3

C# attributes may seem like an insignificant element of C# grammar, but did you know they provide a powerful way to extend your metadata? This goes a long way towards simplifying component-based programming. Here's what you need to know about custom attributesand how to use them.


advertisement
Runtime Attributes
Runtime attributes regroup all attributes that influence the behavior of the runtime. The Just In Time (JIT) compiler looks for these attributes to customize the machine specific assembler it produces. Here are two examples how to use them:

The Layout of Structures
To the surprise of most C++ programmers, when the JIT compiler sees a declaration for a struct, it is not required to respect the order of the fields in memory. Take, for example, this struct:

struct MyStruct { public int X; public string Y; }

The JIT compiler may decide to put Y before X in memory to simplify the job of the garbage collector. This is not desirable when you need to pass instances of this struct outside .NET. The StructLayout attribute indicates the memory layout of a C# struct. In the following code, the struct is marked as sequential, so the JIT compiler respects the X and Y order.


[StructLayout (LayoutKind.Sequential)] struct MyStruct { public int X; [MarshalAs (UnmanagedType.BStr)] public string Y; }

In addition, you can use MarshalAs to specify the corresponding unmanaged representation of fields and parameters.

Imperative and Declarative Security
While component based software is a huge step forward for software productivity, it can be a security concern because it makes it difficult to know whether assemblies are performing dangerous operations behind your back. This is particularly true when you obtain components from the Internet.

.NET resolves this problem by demanding permissions before performing any sensitive operation. Demanding permission involves ensuring that all callers on the stack have permission. You can do this imperatively or declaratively.

Imperative simply means writing code as usual. To perform some sensitive operation, you would first create a corresponding permission and demand it:

public void SomeMethod() { new SomePermission().Demand(); // perform some sensitive operation }

This solution has two drawbacks. First, it is fairly verbose. Second, it is difficult for the client to know about the permission demand because it is buried in IL.

To avoid these issues, specify the permission requirements declaratively. Instead of invoking Demand, add a permission attribute before the method to secure.

[SomePermissionAttribute(SecurityAction.Demand)] public void OtherMethod() { // perform some sensitive operation }

Tools like permview.exe will help you discover such security annotations.

When the JIT compiler comes across this permission attribute, it injects the call to Demand at the beginning of the method call.

Author's Note: The "Attribute" suffix can be omitted in the attribute usage:

[SomePermission(SecurityAction.Demand)] // Note: no "Attribute" suffix public void OtherMethod() { // perform some sensitive operation }

The C# compiler detects that SomePermission does not derive from Attribute and substitutes it for SomePermissionAttribute.

The following table summarizes the runtime attributes.

Attribute Name

Description

System.Serializable

The type is serializable.

System.Runtime.InteropServices.DllImportAttribute

Specifies the DLL name an other information for extern methods.

System.Runtime.InteropServices.MarshalAsAttribute

Specifies how the field or attribute should be marshaled.

System.Runtime.InteropServices.ComImportAttribute

Specifies that the type was previously defined in COM.

System.Runtime.InteropServices.StructLayoutAttribute

Specifies the layout of the structure in memory.

System.Runtime.InteropServices.FieldOffsetAttribute

Specifies the memory offset of a field in a struct.

System.Runtime.InteropServices.GuidAttribute

Specifies the Guid of a COM class or interface.

System.Runtime.InteropServices.InAttribute

Indicates that the parameter is "in".

System.Security.Permissions.CodeAccessSecurityAttribute

 

Specifies a code access permission.

System.Security.Permissions.SecurityPermissionAttribute

 

Specifies a code access permission.

Table 2: Summary of runtime attributes.



Comment and Contribute

 

 

 

 

 


(Maximum characters: 1200). You have 1200 characters left.

 

 

Sitemap