As you've seen this week, Visual Studio .NET provides designers that make working with objects easier. When you added an XML schema to your project two days ago, you were given the Schema Designer. When you need to create a Web service, there was a designer that enabled you to drag objects from the Toolbox onto the Web service. The same holds true for building components with Visual Studio .NET. Depending on that type of project you create or what type of items you add to your projects, Visual Studio .NET provides a Component Designer that enables you to drag and drop items from the Toolbox onto the design surface and expose objects to your component.
This makes it simple to create complex components without having to implement all the code. You can create several types of applications that are considered to be components, based on the interfaces they expose and how they're compiled.
Class Library applications are a template in the New Project dialog. When you create a Class Library application, it's almost the same as adding a class library to your application. The only difference is that you can add classes to any type of application, whereas a Class Library project template is used to specifically compile to a managed DLL (an assembly in .NET terms) that can be consumed by other applications. With Class Library applications, you can implement the functionality of any other type of component that we discuss today. By inheriting from different base classes, you're exposing specific functionality to the application.
For example, when you learned how to create Web services yesterday, your class file inherited the System.Web.Services.WebService class. This made specific ASP.NET functionality available to the class to implement the class as a Web service. The class also implemented the System.ComponentModel.IContainer interface. By exposing this interface to the class, you were given the designer surface to add nonvisual controls or components to the Web service. Even though a Class Library application is a blank slate, you can literally create any type of object with it.
If you create a Class Library application and you want to use the Component Designer to add components from the Toolbox to your class, you can add a component class to your project or you can inherit the correct class that gives you the designer that you need.
The component classes inherit from the System.ComponentModel.Component class. When you add a component class to your solution, the class automatically exposes specific methods that assist in the creation of a component; namely, a designer, the New method, the Dispose method, and initialization code for the class itself.
To give you an idea of what the difference is between a Class Library project template and adding a new component class to an existing class library application, look at the difference between the generated code for a Class Library application and the code generated for the component class item in Listings 14.1 and 14.2.
Public Class Class1 End Class
using System; namespace ClassLibrary4 { /// <summary> /// Summary description for Class1. /// </summary> public class Class1 { public Class1() { // // TODO: Add constructor logic here // } } }
Public Class Component1 Inherits System.ComponentModel.Component #Region " Component Designer generated code " Public Sub New(Container As System.ComponentModel.IContainer) MyClass.New() 'Required for Windows.Forms Class Composition Designer support Container.Add(me) End Sub Public Sub New() MyBase.New() 'This call is required by the Component Designer. InitializeComponent() 'Add any initialization after the InitializeComponent() call End Sub 'Component overrides dispose to clean up the component list. Protected Overloads Overrides Sub Dispose(ByVal disposing As Boolean) If disposing Then If Not (components Is Nothing) Then components.Dispose() End If End If MyBase.Dispose(disposing) End Sub 'Required by the Component Designer Private components As System.ComponentModel.IContainer 'NOTE: The following procedure is required by the Component Designer 'It can be modified using the Component Designer. 'Do not modify it using the code editor. <System.Diagnostics.DebuggerStepThrough()> Private Sub InitializeComponent() components = New System.ComponentModel.Container() End Sub #End Region End Class
using System; using System.ComponentModel; using System.Collections; using System.Diagnostics; namespace ClassLibrary4 { /// <summary> /// Summary description for Component1. /// </summary> public class Component1 : System.ComponentModel.Component { /// <summary> /// Required designer variable. /// </summary> private System.ComponentModel.Container components = null; public Component1(System.ComponentModel.IContainer container) { /// <summary> /// Required for Windows.Forms Class Composition Designer support /// </summary> container.Add(this); InitializeComponent(); // // TODO: Add any constructor code after InitializeComponent call // } public Component1() { /// <summary> /// Required for Windows.Forms Class Composition Designer support /// </summary> InitializeComponent(); // // TODO: Add any constructor code after InitializeComponent call // } #region Component Designer generated code /// <summary> /// Required method for Designer support - do not modify /// the contents of this method with the code editor. /// </summary> private void InitializeComponent() { components = new System.ComponentModel.Container(); } #endregion } }
As you can see, much more code is added based on the type of template you're adding to your application. There are slight differences between the Visual Basic .NET and C# code, but that's purely in the implementation, not the functionality.
Visual Studio .NET incorporates the plumbing code that helps you write the application faster. Because you don't have to remember what you should inherit from, or what syntax is used for each type of component, or what interfaces to implement, you can concentrate on writing the implementation code, not the plumbing code.
The following component project templates have design timegenerated code that's specific to the implementation of the class:
Windows Control Library Used to create Windows Controls. This class inherits from the System.Windows.Forms.UserControl class and exposes the System.ComponentModel.IContainer class that gives you a design surface to drag Toolbox items onto and exposes base class events for all controls in Windows Forms. This template is for designing new Windows Controls and extending existing Windows Controls.
Web Control Library Used to create Web Controls. This class inherits the System.Web.UI.WebControls.WebControl class. This template doesn't give you a design surface to work with, so you must implement the control extensibility without the help of a designer.
ASP.NET Web Service Used to create Web service applications. This class inherits the System.Web.Services.WebService class and exposes the System.ComponentModel.IContainer interface to give you a design surface and make available ASP.NET-specific functionality to your application.
Windows Service Used to create applications that run as Windows services. This class inherits the System.ServiceProcess.ServiceBase class, and exposes the System.ComponentModel.IContainer interface to give you a design surface and specific functionality to work with Windows services.
The following project template is considered a component but doesn't give you a design surface as part of the project template:
Class Library
The following project item is considered a component, but doesn't have a project template but does provide implementation code:
Transactional Component Used to create serviced components designed for COM+. These classes inherit the ServicedComponent class and the default implementation gives you commented code on using SetComplete, SetAbort, and AutoComplete to write components that are transactional.
Each of the project templates I just described is also implemented as items that you can add to your existing applications. To see what types of items you can add to a project, you can right-click on any project name in the Solution Explorer and select Add, New Item. You're prompted to select from the list of available items to add, as Figure 14.1 demonstrates.
The bottom line is that no matter what type of component you're creating, it's still a class file. The specific implementation of the class is what differentiates each type of component in .NET. To understand how a component can be consumed by other applications, you're now going to create a Class Library component, which will make up most of the component development you'll do in real life.