FREE Subscription to Dr. Dobb’s Digest: Same Great Content, New Digital Edition
Site Archive (Complete)
Dobbs M-Dev
Email
Print
Reprint

add to:
Del.icio.us
Digg
Google
Furl
Slashdot
Y! MyWeb
Blink
July 06, 2005
.NET Versus .NOT

Frank Wu
When you're evaluating .NET components, how do you know if they support .NET's unique features, or if they're simply ported from legacy code?

Since the introduction of the Microsoft .NET Framework, third-party .NET components have been increasingly available. These components generally fall into one of two camps:

  • True .NET components, designed with the .NET Framework in mind, take advantage of the .NET Framework and provide necessary .NET functionality in terms of design time and runtime.
  • What I call ".NOT components," largely translated from legacy components with native programming languages at the syntax level, support few .NET features.

When evaluating a component, it is important to identify which type the candidate component is. Here, I present some guidelines for evaluating .NET components and identifying which type of a component you're considering.

There are different approaches to developing .NET components, ranging from building from scratch to porting from legacy code. From the vender's point of view, porting lets them quickly enter the market with low cost. The trade-off is the components might not appreciate the .NET Framework and lack in features. For example, a component ported from C++ or Visual Basic may not have data binding and designer capability. Moreover, it is costly and probably impossible to have those missing features later on.

From the customer's perspective, an in-depth evaluation is necessary to recognize important missing features and impact to your development. Understand that I am not saying .NOT components are necessarily a bad choice, but you have to consider what you can live without in terms of capabilities. For instance, is there any impact to your architecture if a component has no interface, no property, and no data binding? Is there any impact to the development and maintenance?

After you have installed the component being evaluated, its help, user's guide, and samples are good starting points for evaluation. The evaluation includes whether the component uses property, interface, data binding, and the like.

Unlike C++, in which a class exposes information with public fields, .NET languages like C# and VB.NET provide properties for exposing information. The benefits are that properties can be used for data binding, but public fields cannot. Properties work with visual designers such as Visual Studio .NET, public fields don't. If a component exposes data primarily via public fields instead of properties, this is a strong indication that the component was ported from a legacy component. It is hard to bind the data, and it won't be able to work with visual designers.

In modern programming languages, an interface defines a contract. The benefit is that classes that implement the interface are loosely coupled. In architectures, components are loosely coupled. If a component has no interface exposed, it is another hint showing the component was a .NOT component.

Data binding is a technique for associating data sources with controls--including ASP.NET server controls and Windows Forms controls. The direct benefit of data binding is significantly reducing the development cost. If a component has no data binding capability, you should question if it was ported from a legacy component.

If the above evaluation approaches do not give you sufficient information, you can decompile the component to investigate its internals. Presently, most components are not encrypted, and are fairly easy to decompile using tools such as Lutz Roeder's Reflector which is powerful, easy to use, and free.

Lutz Roeder's Reflector is a class browser for .NET components. It displays assemblies, namespaces, types, members, XML documentation, and the like. The tool supports C#, VB.NET, and Delphi.NET, and has an add-in feature to let users add additional components. To use it for code decompilation, you need to add Reflector.FileDisassembler, an add-in component.

Denis Bauer's Reflector.FileDisassembler is an add-in for the Reflector. It lets you decompile .NET assemblies and dump the output to files of any Reflector supported language. After you download and decompressed the above two files, they need a little configuration work:

  1. Launch Reflector and go to View | Add-ins menu. This open the Add-ins dialog box. Click Add button, browse to the Reflector.FileDisassembler.dll file, and select it. Close the dialog box. Now you should find a new menu item called File Disassembler under Tools menu.
  2. Open the Options dialog box, select the Languages combo box to the programming language you want the output source code to be written with. Leave the other controls as default, and close the dialog box.

You can decompile the component with a language which is different from the language the component programmed with. Therefore, you don't have to know with what programming language the component programmed. Now it's time to have fun with the component you are evaluating. In Reflector, click File | Open menu to open your .NET component. Then select the file and run File Disassembler. Presto! You get the source code of the component. In following discussion, I assume the component was decompiled to C# code.

.NET languages use properties for exposing information. .NET components use this feature extensively. However, if a component not only exposes data via public fields, but also uses few properties internally, this is a strong indication that the component was ported from a legacy component.

.NET components work with visual designers. .NET components include visual and non-visual components. ASP.NET server controls and Windows Forms controls are visual components. There is a wide range of non-visual components. They are derived from the System.ComponentModel.Component class. A .NET component can be hosted in any object that implements the IContainer interface, and can get services from its container. If your evaluating component did not provide this feature and you could not find a reason, that component is probably a .NOT component.

.NET components use data binding to reduce code, especially for language pre-built data types. However, when data binding is fit in the needs and the component does not use it, this is another indication that the component was ported.

.NET languages like C# and VB.NET introduced key words as and is. The advantages over explicitly casting they provide includes better performance for casting, no exception raising, and so on. I won't compare the details of different casting approaches here since there are numerous available sources for this information. However, I will illustrate the difference to help you identify .NET and .NOT components.

Suppose class Derived is derived from class Base, and you want to cast Derived to Base. If you find the source code in a component has few as and is keywords, but includes code snippets such as this:


Base d = new Derived();
...
try
{
   Base b = (Base) d;
...
}
catch(Exception exp)
{
   ...
}
This suggests that the source code was translated from C++ to C#, or the vender's coding style is not elegant. It is worse if you find the pattern has no try and catch block, such as:

Base d = new Derived();
...
Base b = (Base) d;

With the as keyword, a much better pattern is:

Base d = new Derived();
...
Base b = d as Base;
if(b != null)
{
   ...
}

Alternatively, you can use the is keyword:

Base d = new Derived();
...
if(d is Base)
{
   Base b = d as Base;
}


Both of these patterns are safer and faster than explicitly casting. However, there are some cases you need explicitly casting; for instance, you simply need to catch and handle the exception.

An interface defines a contract among classes. A class or struct that implements an interface must adhere to its contract. Using interface can reduce object coupling. It would be odd to see a .NET component that has few interfaces exposed. If a component not only has no interface exposed, but also has few interfaces internally, this is another hint that the component was ported from legacy code.

In this article, I introduced techniques of .NET components evaluation I used. They are not limited to those discussed above. You probably can work out your extension.

Frank W. Wu has focused on .NET application development since the release of the .NET Framework 1.0. He can be contacted at frankwwu@hotmail.com

TOP 5 ARTICLES
No Top Articles.



MICROSITES
FEATURED TOPIC

ADDITIONAL TOPICS

INFO-LINK