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
 

How Attributes Can Help You Debug an App

Learn how attribute-driven programming can help debug and maintain your applications much more efficiently.


advertisement
Attributes provide a great way to improve the readability and maintenance of your application's code. You can decorate your classes, methods, properties, etc. with metadata information and then inspect these elements as and when needed. This article discusses how attributes can play a major role in improving the debugging experience in applications.

Prerequisites

To work with the code examples illustrated in this article, you should have one of the following installed in your system:

  • Visual Studio 2008
  • Visual Studio 2010
Before we delve deep into using attributes to help debug our applications, let's take a quick tour of the basic concepts.



[login]

What are Attributes? How Do they Help?

An attribute is used to associate declarative information on your code. Attributes can be used to decorate your classes, methods, properties, etc and are stored with the metadata information of the element to which it is associated. Such attributes can then be retrieved by reflecting on those types at runtime. The element (class, method, property, etc) to which the attribute is applied is known as the attribute target or the target of the attribute.

The following are the supported attribute targets:

  • All
  • Assembly
  • Class
  • Constructor
  • Delegate
  • Enum
  • Event
  • Field
  • Interface
  • Method
  • Module
  • Parameter
  • Property
  • ReturnValue
  • Struct
Essentially, you can use attributes to associate some pre-defined information with a target element. The target element can in turn be one of: class, assembly, property, struct, another attribute or any other element listed above. This information that an attribute contains is known as metadata. The following code snippet illustrates how an attribute is used to define a web method:

[WebMethod] public String GetMessage() { return "Welcome"; }

The WebMethod attribute in the code snippet above exposes the GetMessage() method as a web method.

Attributes are typically of two types: intrinsic attributes and custom attributes. While the former relates to attributes that are defined in the CLR, the later relates to classes that are derived from the Attribute class.

Using the Obsolete Attribute

Let's consider the following class:

public class Product { public int ProductID { get; set; } public String ProductDescription { get; set; } public double ProductPrice { get; set; } public int ProductQuantity { get; set; } public int ProductReOrderLevel { get; set; } public int ProductReOrderQuantity { get; set; } }

As you can see, the Product class is a business entity that contains a list of properties that pertain to the Product entity. Now, let create another class called ProductBO that would contain one or more methods to perform CRUD operations. Here is how the ProductBO class would look like at first glance:

public class ProductBO { public void CreateNewProduct(Product product) { //Code to create a new Product. This method calls the DAL and passes this instance to persist data in the DB. } }

The following code snippet illustrates how you can create an instance of the Product class and then pass this instance to the CreateNewProduct() method to create a new Product instance in the database:

Product product = new Product(); product.ProductID = 1234; product.ProductDescription = "Laptop"; product.ProductPrice = 35750.00; product.ProductReOrderLevel = 150; product.ProductReOrderQuantity = 200; ProductBO productBO = new ProductBO(); productBO.CreateNewProduct(product);

Now, after a certain point in time you realize that you need a different version of the CreateNewProduct() method and would like not to use the existing method anymore. So, what should you do? If the method is deleted, any code in your application that does use this method wouldn't compile, isn't it? So, that would obviously not be a good choice, right? How do you as the architect communicate to your developers that this method is deprecated? Here's where the Obsolete attribute comes into play. The code snippet below illustrates how you can have another similar method and mark the previous method with the Obsolete attribute:

[Obsolete("This method is deprecated. Use the method Create (Product) instead.", false)] public void CreateNewProduct(Product product) { //Code to create a new Product. This method calls the DAL and passes this instance to persist data in the DB. } public void Create(Product product) { //Code to create a new Product. }

The second parameter in the Obsolete attribute is set to "false". This implies that the code would compile but any call to the CreateNewProduct() method would issue a warning. The complete code listing for this example follows:

using System; using System.Data; namespace Attributes { public class Product { public int ProductID { get; set; } public String ProductDescription { get; set; } public double ProductPrice { get; set; } public int ProductQuantity { get; set; } public int ProductReOrderLevel { get; set; } public int ProductReOrderQuantity { get; set; } } public class ProductBO { [Obsolete("This method is deprecated. Use the method Create (Product) instead.", false)] public void CreateNewProduct(Product product) { //Code to create a new Product. This method calls the DAL and passes this instance to persist data in the DB. } public void Create(Product product) { //Code to create a new Product. } } class Program { static void Main(string[] args) { Product product = new Product(); product.ProductID = 1234; product.ProductDescription = "Laptop"; product.ProductPrice = 35750.00; product.ProductReOrderLevel = 150; product.ProductReOrderQuantity = 200; ProductBO productBO = new ProductBO(); productBO.CreateNewProduct(product); //Warning! productBO.Create(product); //This compiles fine! } } }

Applying Attributes in Code Debugging

While debugging your code, you might encounter situations where you would like to step through certain portions of your code. This implies, you would like to ensure that certain portions of your code would not be debugged. How can you do that? Thanks for the DebuggerStepThroughAttribute and the DebuggerHiddenAttribute classes -- you can now specify which portion of your code the debugger shouldn't step into.

The DebuggerStepThroughAttribute class can be used to step through code that you would not like to debug. This class extends the Attribute class and belongs to the System.Diagnostics namespace. Here is how the DebuggerStepThroughAttribute class looks like:

[SerializableAttribute]
[AttributeUsageAttribute(AttributeTargets.Class|AttributeTargets.Struct
|AttributeTargets.Constructor|AttributeTargets.Method, Inherited=false)] [ComVisibleAttribute(true)] public sealed class DebuggerStepThroughAttribute : Attribute So, if you specify this attribute in the Create() method as shown below, the debugger
would just step through -- it wouldn't stop at the method even if a break point is set.
[DebuggerStepThroughAttribute()] public void Create(Product product) { //Code to create a new Product. }

Now, even if you set the DebuggerStepThroughAttribute in your method, you can still set break points inside your method and still step into the method by pressing F11 while you are debugging your code. What if you would like to completely ignore a particular method or property while debugging your code? This is where the DebuggerHiddenAttribute comes into play. If you use this attribute, the debugger would never enter the method's code even if explicit break points are set. Here's an example:

[DebuggerHiddenAttribute()] public void Create(Product product) { //Code to create a new Product. }

Using Debugger Display Attribute to Improve Debugging Experience

In this section we will discuss how attributes can be used to decorate your business objects. The Debugger display attributes in .NET can be used to specify the runtime behaviour of a type while debugging is in progress. The following are the supported debugger display attributes:

  • DebuggerDisplayAttribute -- this is used to control how a type is displayed in debugger windows. The DebuggerDisplayAttribute can be applied to a class, struct, delegate, field, enum, property or an assembly.

  • DebuggerBrowsableAttribute -- this is used to control how a field or property would be displayed in debugger windows

  • DebuggerTypeProxyAttribute - this is used to specify a substitute type or a proxy. The DebuggerTypeProxyAttribute can be applied to a class, struct or assemblies.

The following code snippet illustrates how the DebuggerDisplay attribute can be used:

[DebuggerDisplay("FirstName = {_firstName} LastName = {_lastName}]

To specify the DebuggerBrowsable attribute, you can write the following code:

[DebuggerBrowsable(DebuggerBrowsableState.RootHidden)]

And, you can specify the DebuggerTypeProxy attribute as shown below: [DebuggerTypeProxy(typeof(Product))]

Suggested Readings

Here are a few good links to resources on this topic for further study:

http://msdn.microsoft.com/en-us/library/ms228992.aspx

http://msdn.microsoft.com/en-us/library/x810d419.aspx

Summary

Attributes provide a great way to specify declarative information to the types in your application's code. This information can then be retrieved at a later point in time using reflection, or, can help you in your debugging experience. In this article we discussed how attribute driven programming can help us debug and maintain our applications much more efficiently. Happy reading!



   
Comment and Contribute

 

 

 

 

 


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

 

 

Sitemap