WriteLine("Car turns left.")
End Sub
Overrides Public Sub TurnRight( )
Console.WriteLine("Car turns right.")
End Sub
Overrides Public Sub ApplyBrakes( )
Console.WriteLine("Car trying to stop.")
throw new Exception("Brake failure!")
End Sub
End Class
56
.NET Framework Essentials
With this code, we can build a DLL using the command-line VB.NET compiler, as follows: vbc /r:vehicle.dll /t:library /out:car.dll car.vb
Since we want the VB.NET compiler to generate a DLL, we must signal this by using the /t:library option. Also, since Car derives from Vehicle, the VB.NET compiler must resolve the references to Vehicle. We can tell the VB.NET compiler the location of external references using the /r: option. It is important to note that you don't need to have the source code for the vehicle DLL to reuse its code because all type information can be obtained from any .NET assembly. In addition, you should note that from this example, we have proven that you can derive a VB.NET class from a Managed C++
class.
3.3.3 Plane Class in C#
Now let's use C# to develop the Plane class, which derives from the Vehicle class written in Managed C++. Similar to the Car class, the Plane class implements the three virtual functions from the Vehicle class. Unlike the Car class, though, the ApplyBrakes( ) method of this class doesn't throw an exception.
using System;
public class Plane : Vehicle
{
override public void TurnLeft( )
{
Console.WriteLine("Plane turns left.");
}
override public void TurnRight( )
{
Console.WriteLine("Plane turns right.");
}
override public void ApplyBrakes( )
{
Console.WriteLine("Air brakes being used.");
}
}
You can build a DLL from this code using the following command:
csc /r:vehicle.dll /t:library /out:plane.dll plane.cs
Notice that we have used the /r: option to tell the C# compiler that Vehicle is defined in vehicle.dll.
3.3.4 Test Driver in C#
Having developed vehicle.dll, car.dll , and plane.dll, we are now ready to demonstrate that polymorphism and exception handling work across different languages. Written in C#, the upcoming code listing contains a Main( ) method with a Vehicle reference and an exception handler.
Inside the try block, we first instantiate a Plane class and refer to this instance using the local Vehicle reference. Instead of telling the Pla ne to TurnLeft( ) or ApplyBrakes( ), we tell the Vehicle to do so.
Similarly, we instantiate a Car and refer to this instance using the local Vehicle reference. Again, instead of telling the Car to TurnLeft( ) or ApplyBrakes( ), we tell the Vehicle to do s o. In both cases, we tell the Vehicle either to TurnLeft( ) or ApplyBrakes( ), but the actual vehicle that employs 57
TurnLeft( ) or ApplyBrakes( ) is the Plane instance in the first case and the Car instance in the second case; that's polymorphism, and it works across languages.
You should note that the second call to ApplyBrakes( ) would cause an exception because we threw an exception from Car's ApplyBrakes( ). Although Car's ApplyBrakes( ) was written using VB.NET, we could still catch the exception that it's throwing in C#, proving that exception handling works across languages.
using System;
class TestDrive
{
public static void Main( )
{
Vehicle v; // Vehicle reference
try
{
Plane p = new Plane( );
v = p;
v.Turn Left( );
v.ApplyBrakes( );
Car c = new Car( );
v = c;
v.TurnLeft( );
v.ApplyBrakes( ); // Exception
}
catch(Exception e)
{
Console.WriteLine(e.ToString( ));
}
}
}
If you want to test out these features, you can create an EXE using the following command: csc /r:vehicle.dll;car.dll;plane.dll /t:exe /out:drive.exe drive.cs
Since we have used the Vehicle, Car, and Plane classes in this code, we must include references to vehicle.dll, car.dll, and plane.dll. In addition, since we are building an EXE, we need to signify this to the C# compiler using the /t:exe option. Once you have built this EXE and executed it, you get the following output:
Plane turns left.
Air brakes being used.
Car turns left.
Car trying to stop.
System.Exception: Brake failure!
at Car.ApplyBrakes( )
at TestDrive.Main( )
As expected, the plane first turns left and then uses its air brakes. Then the car turns left, tries to stop, but can't, so it throws an exception, which is caught in the Main( ) method.
In this simple example, we have shown that you can now take advantage of inheritance, polymorphism, and exception handling across different languages in the .NET Framework.
58
.NET Framework Essentials
3.4 Summary
We started this chapter by tellin g you that .NET provides a common programming model, which reduces the learning curve and increases productivity. Once you've learned how to do something using the classes in the .NET Framework, this knowledge will transfer to any .NET language. We then illustrated that we could write the same type of code, supporting major .NET features, in any given language. Finally, we proved to you that .NET indeed supports language integration, which is something never before possible using Microsoft platforms and too ls, prior to .NET.
59
60
.NET Framework Essentials
Chapter 4. Working with .NET Components
Having seen the language-integration examples in the previous chapter, we know that all .NET
assemblies are essentially binary components.[1] You can treat each .NET assembly as a component that you can plug into another component or application, without the need for source code, since all the metadata for the component is stored inside th e .NET assembly. While you have to perform a ton of plumbing to build a component in COM, you need to perform zero extra work to get a component in .NET, as all .NET assemblies are components by nature.
[1] Remember, as we explained in Chapter 1, we're using the term "component" as a binary, deployable unit, not as a COM class.
In this chapter, we examine the more advanced topics, including component deployment, distributed components, and enterprise services, such as transaction management, object pooling, role -based security, and message queuing.
4.1 Deployment Options
For a simple program like hello.exe that we built in Chapter 2 , deployment is easy: copy the assembly into a directory, and it's ready to run. When you want to uninstall it, remove the file from the directory. However, when you want to share components with other applications, yo u've got to do some work.