Comments
bruce.armstrong wrote: Somebody just said it better than I did, and with more chops to say it: Open Letter to Mark Zuckerberg, Sheryl Sandberg & Facebook Mobile
Cloud Expo on Google News


2008 West
DIAMOND SPONSOR:
Data Direct
SOA, WOA and Cloud Computing: The New Frontier for Data Services
PLATINUM SPONSORS:
Red Hat
The Opening of Virtualization
GOLD SPONSORS:
Appsense
User Environment Management – The Third Layer of the Desktop
Cordys
Cloud Computing for Business Agility
EMC
CMIS: A Multi-Vendor Proposal for a Service-Based Content Management Interoperability Standard
Freedom OSS
Practical SOA” Max Yankelevich
Intel
Architecting an Enterprise Service Router (ESR) – A Cost-Effective Way to Scale SOA Across the Enterprise
Sensedia
Return on Assests: Bringing Visibility to your SOA Strategy
Symantec
Managing Hybrid Endpoint Environments
VMWare
Game-Changing Technology for Enterprise Clouds and Applications
Click For 2008 West
Event Webcasts

2008 West
PLATINUM SPONSORS:
Appcelerator
Get ‘Rich’ Quick: Rapid Prototyping for RIA with ZERO Server Code
Keynote Systems
Designing for and Managing Performance in the New Frontier of Rich Internet Applications
GOLD SPONSORS:
ICEsoft
How Can AJAX Improve Homeland Security?
Isomorphic
Beyond Widgets: What a RIA Platform Should Offer
Oracle
REAs: Rich Enterprise Applications
Click For 2008 Event Webcasts
SYS-CON.TV
Top Links You Must Click On


Generic Object Configuration
A total solution

In a previous article (DNDJ Volume 3, issue 4), I discussed an application that had to load, process, and transmit data received from multiple customers. The system had to perform a specific set of tasks or steps for each customer. Because of the diverse needs of each customer, however, the actual implementation of each step could vary widely, often on a per-customer basis. In addition, new customers would be added long after the application was completed, and the unique requirements of these new customers would also have to be met.

The system accomplished these goals by allowing each step to dynamically load an appropriate object from disk. A database kept track of which object would perform a particular step for a particular customer. Because these objects were loaded dynamically, new objects could be developed as needed, allowing new customers to be serviced without having to alter the existing objects or the application. By having each external object implement a specific interface, and by utilizing the .NET framework's ability to load objects from external assemblies, the application became a flexible framework for customer-specific processing.

While this approach did solve the problem, it also introduced a new one: How does one write a configuration program for an application that works in this manner? The standard approach to writing a configuration program is to "hard code" a certain amount of knowledge about each object that can be configured. This was not only distasteful to me, but it didn't answer my main question: How can the configuration program accommodate objects that will be created long after the configuration program itself is written? Steve Henke (a fellow co-worker and the ultimate author of the configuration program) and I got together to hammer this out.

During a brainstorming session, we determined that the best approach was to somehow encode each object with "metadata" that could be read by the configuration program. This "metadata" would describe the unique configuration needs of each object. We then remembered that the .NET framework provided support for class and method attributes, and that custom attributes could be created. This turned out to be the answer. We created one custom attribute that each configurable object would use to describe its configuration requirements. We created another custom attribute for each property in that object, so that the properties could be displayed on screen in an appropriate manner. The configuration program used some of the classes in the Reflection namespace to read this data. This approach allowed each object to provide enough information about itself that a generic configuration program could be written.

The remainder of this article describes the .NET technologies used by this configuration system. It shows how to create custom attributes for your own classes and how to read the information that these attributes supply. It also explains some of the challenges that we faced, and how implementing a custom base class for our configurable objects allowed these challenges to be overcome. Finally, it demonstrates how the Reflection namespace classes can be used to access object properties and invoke object methods in a completely generic manner.

Attributes
The .NET framework supplies nearly two hundred built-in attributes. These attributes control how certain classes, methods, and properties are used. For example, in Listing 1, we see the standard "HelloWorld" Web service method that is created by a Web service project in Visual Studio. The attribute is the "<WebMethod()>" text found directly in front of the "HelloWorld" function definition. This attribute informs the .NET framework that the method should be made available to remote clients as a Web service method. The attribute accepts certain parameters that give additional control to the developer. In this example, I've added parameters to specify that responses should be cached for 30 seconds, and that remote clients should access the method with the name "SayHello." In Listing 2 we have an Employee class with two public fields. The entire class is marked "serializable," which means that it can be reduced to an XML or binary-encoded string representation. When the class is serialized, the "LastName" field will be included, but the "FirstName" field will not. This is because the "FirstName" field is modified with the "<NonSerialized()>" attribute.

As you can see, by using the .NET framework's built-in attributes, the developer can exert a good deal of control over how particular classes, properties, and methods are processed. Many of these built-in attributes can be applied not only to framework classes, but to those created by the developer as well. In addition, when existing attributes are not sufficient, custom attributes can be created to fill the gap.

Custom Attributes
Custom attributes are simply user-defined types that inherit from System.Attribute. A single custom class represents a particular custom attribute in a one-to-one relationship. Attribute parameters are represented via fields and/or properties of this custom class. In our configuration scenario, each configurable object needed an attribute that the configuration program could use to determine how to work with that object. Listing 3 shows the definition of such an attribute. The "DataClassAttribute" is defined as an ordinary class that inherits from System.Attribute. The developer can control where the custom attribute can be used by attaching an "<AttributeUsage()>" attribute to the class definition. In this case, the attribute can be used for classes only. Any attempt to place this attribute on a method or property would fail. Public fields or properties can be created to store the parameter information provided in the custom attribute.

Listing 4 shows how the Employee object could use the DataClassAttribute to provide information to a configuration program. (Note that in VB.NET, the word "Attribute" is used in an attribute definition, but is omitted when the attribute is used. The "DataClassAttribute" is specified correctly as "DataClass" in this example.) Using this information, a program could determine that the Employee class is configurable (IsConfigurable:=True), that it should be displayed on screen with a particular label (Label:="Employee"), and that the names of the Employee object's methods are "Delete," "Insert," "Update," and "Get" (DeleteMethod, GetMethod, etc.). The program could do this generically, without having to have specific information hard-coded into it.

Our configuration program also needed to be able to extract information about each configurable object's properties. The ConfigurationAttribute in Listing 5 was created for this. This attribute, which can be used only on properties, provided information about how the property should be displayed on screen and how it should be validated. An example of its actual use is shown in Listing 6.

Custom Object Base Class
Using two custom attributes, each object could be "decorated" with enough data to allow the configuration program to remain generic. But how was the configuration application supposed to read this data? The Reflection namespace provided the answer. Using reflection, the custom attributes could be read and their data used to configure the objects.

To simplify things, we decided to derive each configurable object from a common base class that would encapsulate all of the Reflection code. In Listing 7, you can see examples of some of the methods of this base class. First, a new class called ConfigurationInfo was created to hold the actual property attribute information. This class was derived from our ConfigurationAttribute class, but included fields to specify the object's property name and type. Next, the GetPropertyConfigura-tionData method was used to return a list (actually a HybridDictionary) of these ConfigurationInfo objects. It did this by iterating through each explicitly declared public property and processing only those properties that possessed a ConfigurationAttribute. For those properties, a ConfigurationInfo object was instantiated and populated with data about the property. This included the custom attribute data. The GetClassConfigurationData method performed a similar task for the configurable object itself, returning a DataClassAttribute to the caller.

Once the base class existed, we found many other uses for it. Code for common tasks such as validation and exception handling was moved to the base class. This served to further simplify the configurable objects themselves.

Configuration Program
With our custom attributes created, almost all of the pieces were in place. Custom objects could provide specific data about themselves to a configuration program in a generic way. All that was needed was a configuration program that could examine a list of assemblies, obtain information about any configurable objects contained in those assemblies, and dynamically create an appropriate user interface. The list of configurable assemblies was stored in a database to help ensure that only authorized assemblies were processed. Given this list, the code in Listing 8 could return a list of DataClassAttributes that represent all of the configurable objects contained in one of those assemblies. From there, each object could be queried for its configurable property and method information.

The last remaining problem was how to examine and/or invoke an object's properties and methods in a generic manner. The Reflection namespace once again provided a ready-made solution. A PropertyInfo object was used to represent each property of the configurable object. The PropertyInfo object's GetValue and SetValue methods were used to read and write property values. Similarly, a MethodInfo object was used to represent each method of the configurable object, and the MethodInfo's Invoke method used to execute the appropriate methods.

During the design of our customer classes, we had already decided that each class would contain shared (static, or non-instance) methods for managing the creation, modification, and deletion of instances of the class. This turned out to be fortuitous, because the configuration program could use these shared classes to create, modify, and delete object instances using methods of the MethodInfo class. No further code had to be created to manage the objects.

The configuration program could now obtain a list of configurable objects, query those objects for information about any properties that needed to be configured, and invoke the appropriate add/edit/delete methods as needed. All of this could be done without having to hard-code any object-specific information into the configuration program.

Total Solution
This article, together with the previous one, shows our total solution for the use and configuration of customer-specific objects. These objects can be developed at any time, either during the application development cycle, or long thereafter. The application can dynamically load these objects as needed and manipulate their properties and methods via an appropriate object interface. The configuration program can be used to modify the settings for these objects without having to know anything about the objects themselves. All code is written generically, allowing objects to be added or removed from the system without affecting any existing code. This is why, after all, I call them "hot-swappable" objects.

About Jerry Dixon
Jerry Dixon is a senior developer and architect for ACH Food Companies in Memphis, Tennessee. Over the past 16 years he has led development projects for a number of enterprise, mid-level, and small business organizations. While he has fulfilled multiple roles as an infrastructure designer, database administrator, and software developer, he specializes in XML, SQL and ASP.NET. He is a co-leader and frequent presenter at the Memphis .NET User Group. Jerry holds the following Microsoft certifications: MCSD (VB 6.0 and .NET), MCDBA (SQL 2000), MCSA (Windows 2000 and 2003), MCSE (Windows 2000), MCAD (.NET), MCT. He resides in Olive Branch, MS with his wife and son.

In order to post a comment you need to be registered and logged in.

Register | Sign-in

Reader Feedback: Page 1 of 1

Enterprise Open Source Magazine Latest Stories . . .
Before embarking on using open source cloud technology for your web property, a basic understanding of cloud, as it’s used in the industry, is essential. While there might be exceptions, here are the definitions. A software application delivered on the web instead of installing standa...
Businesses today generate billions of events or 100s of TBs of data in a month. These data contain valuable insights into customer behavior, key trends, buying patterns, etc. If these are successfully mined, they can lead to successful decision-making to maximize revenue and traffic fo...
Grid Dynamics, an eCommerce technology solutions company, and GridGain Systems, makers of an open source in-memory platform for Big Data processing, on Wednesday announced the expansion of their partnership which began in 2008. Grid Dynamics provides personalization and big data solut...
Private clouds solve many problems for enterprises and bring unique operational challenges along with them. There are dozens of companies of all sizes that will build you a private cloud and turn over the keys – then what? Trying to convert a traditional enterprise IT operations team t...
The networking industry has gone through different waves over last 30+ years. In the ’80s, the first wave was all about connecting and sharing; how to connect a computer to other peripheral devices and other computers. There were many players who developed technology and services to ad...
If your organization already uses virtualized infrastructure, you are well on your way to providing IT as a Service. But as businesses demand faster results in today’s competitive market, organizations look to gain more benefits from cloud computing than just virtualized infrastructure...
Subscribe to the World's Most Powerful Newsletters
Subscribe to Our Rss Feeds & Get Your SYS-CON News Live!
Click to Add our RSS Feeds to the Service of Your Choice:
Google Reader or Homepage Add to My Yahoo! Subscribe with Bloglines Subscribe in NewsGator Online
myFeedster Add to My AOL Subscribe in Rojo Add 'Hugg' to Newsburst from CNET News.com Kinja Digest View Additional SYS-CON Feeds
Publish Your Article! Please send it to editorial(at)sys-con.com!

Advertise on this site! Contact advertising(at)sys-con.com! 201 802-3021


SYS-CON Featured Whitepapers
ADS BY GOOGLE