February 2004 - Posts

1st Meeting of the Jackson .NET Users Group

Terry Cole, the leader of the Jackson .NET User's Group, invited Jon Box to speak at their inaugural meeting.  (I tagged along.  Somone has to keep Jon in line.)  Jon and I gave a general overview of .NET from a VB perspective, and tried to show some of the cool features of .NET.

Here are some pictures.  In the first, I am once again plugging the book, “.NET Game Programming with DirectX 9.0” by Alexandre Santos and Ellen Hatton.  I love DirectX!  (Take a look.  I am the hairless one in the red shirt.)

Finally, anyone who can help grow the Jackson user group:  do it!  We should all try to advance the adoption of this great tool.

Overridden Properties handled differently in C# and VB

(Check here for an update to this post!)

I have a game in my mind that I keep trying to program.  I'm sure many people have done this; the game never really gets anywhere, but it's always “getting there“.  Anyway, I wrote many of the classes for this game in C#.  Later, for no really good reason, I decided to translate these classes to VB.  (Yes, I'm one of those guys.)

I discovered an interesting fact:  C# and VB handle overloaded properties differently.  Let's look at an example.

What I want to do is to make a read/write property in my base class, then override this property in a derived class.  The property in the derived class should be read-only. In C#, this works as expected.  However, in VB, this gives a compiler error that states that the base class cannot be overridden because the derived class's property differs from the base class's property by “readonly or writeonly.“  Why the difference?

In C#:
public abstract class Weapon
{
     private bool _IsLimited = false;

     public Weapon()
     {
     }

     public virtual bool Limited
     {
          get
          {
               return _IsLimited;
          }
          set 
          {
               _IsLimited = value;
          }
     }
}

public abstract class BeamWeapon: Weapon
{
     public BeamWeapon()
     {
         
base.Limited = false;
     }

     public override bool Limited
     {
          get
          {
               return base.Limited;
          }
     }
}

 

In VB:
Public MustInherit Class Weapon

     Private _IsLimited As Boolean

     Public Sub New()
     End Sub

     Public Overridable Property Limited() As Boolean
          Get
               Return _IsLimited
          End Get

          Set(ByVal Value As Boolean)
               _IsLimited = Value
          End Set
     End Property
End Class

Public MustInherit Class BeamWeapon
     Inherits Weapon

     Public Sub New()
          
MyBase.Limited = False
     End Sub

     ' This causes an error!
     Public Overrides ReadOnly Property Limited() As Boolean
          Get
               Return MyBase.Limited
          End Get
     End Property
End Class

Custom XML Serialization

I recently created an application that needed a fairly deep class hierarchy.  One class contained another class, which contained another, and so on.  I needed to find an easy way to serialize this object and store it in a database.  I found a post on Jeff Kirwan's blog that showed how to serialize an object to XML, which could then be placed into a database.  This seemed to be an easy solution to my problem....

Then I got into trouble.  I needed to store the class data in relational form in the database, so that some of this data could be referenced by other stored procedures.  (The class hierarchy actually represents configuration data for an application.)  This is easy to do with SQL via OPENXML.  (See my Memphis .NET User's Group presentation.)  However, pulling this data out of SQL proved to be a problem.  The class structure was DEEP.  It took a LOT of SQL code to rebuild the XML, so that the object could be deserialized.  I had to find a better way.

I turned to the ISerializable interface.  By implementing this interface, you can control how your class is serialized.  Cool!  This was the solution to my problem, right?  Wrong!  The ISerializable interface does not work when you use the XMLSerialier.  I wanted XML and the ISerializable interface gave me a binary serialization. 

After thinking a few unmentionable thoughts about the world in general, I finally found a real solution.  There is an undocumented interface called IXmlSerializable.  If you look this up in the .NET help, you will see that they say this is an internal interface and that you should not use it.  However, if you look here, you can see that this interface IS documentated in Longhorn.  Feeling a little better now, I tried it.  It works great.

Serialization Methods:


XmlSchema IXmlSerializable.GetSchema()
{
     return null;
}

void IXmlSerializable.ReadXml(XmlReader Reader)
{
     // code to read in XML document goes here
}

void IXmlSerializable.WriteXml(XmlWriter Writer)
{
     // code to write XML document goes here
}

Now I can have a deep class structure in my code, and serialize this as a very flat XML document.  Then, instructing SQL Server to create this XML document from the database is very simple and easy to maintain.

Memphis DevDays Speakers

It's official.  You can now go to the DevDays site and see the list of local speakers.  As I said in a previous post, I know most of these guys personally.  I would make every effort to go see these guys.  Remember, there are two tracks; Smart Client and Web Development.

Come see me present session 2 of the Web Track.  In this session, entitled “Threats and Threat Modeling - Understanding Web Application Threats and Vulnerabilities”, I get to show you how most web sites contain insecure code

I can't wait to see you there.  I get to scare your pants off!

Use Isolated Storage for Configuration Data

When storing user-specific program settings, I like using the Isolated File Storage capability of Windows and .NET.  This allows a program to place files into a location that is specific to that user and assembly.  Here's how:

Saving:
Dim isoFile As IsolatedStorageFile
Dim isoStream As IsolatedStorageFileStream
Dim bf As BinaryFormatter
Dim optMap As Hashtable
 
optMap = New Hashtable()
optMap.Add(“Key1”, 12)
optMap.Add(“Key2”, 20)
 
isoFile = IsolatedStorageFile.GetUserStoreForAssembly
isoStream = New IsolatedStorageFileStream(“MyApp.cfg”,_ IO.FileMode.Create, isoFile)
bf = New BinaryFormatter()
bf.Serialize(isoStream,optMap)

Loading:
Dim isoFile As IsolatedStorageFile
Dim isoStream As IsolatedStorageFileStream
Dim bf As BinaryFormatter
Dim optMap As Hashtable
 
isoFile = IsolatedStorageFile.GetUserStoreForAssembly
isoStream = New IsolatedStorageFileStream_(FILENAME,IO.FileMode.OpenOrCreate, isoFile)
 
If isoStream.Length > 0 Then
bf = New BinaryFormatter()
      optMap = CType(bf.Deserialize(isoStream),Hashtable)
 
      x = CType(optMap(“Key1”),integer)
      y = CType(optMap(“Key2”),integer)
EndIf

Add IntelliSense to your XSLT files in .NET

Have you tried creating and editing XSLT files in .NET?  If so, you know that the XML editor doesn't provide much in the way of help.  Fesersoft comes to the rescue!  The have developed an XSLT schema, so that .NET will provide IntelliSense for XSLT files.  Check out their .NET page and see for yourself.

Way to go Fesersoft!

Pagination in HTML Reports

There are many times when I have to create reports in Web Pages.  These reports typically span multiple printed pages, and each page needs to have a common header.  How can this be done easily?  CSS comes to the rescue:

<table style="table-layout:fixed">
    <colgroup>
        <col width="150"/>
        <col width="100"/>
        <col width="150"/>
    <colgroup>
    <thead style="display:table-header-group">
        <tr>
            <td>Header column 1 (150)<td>
            <td>Header column 2 (100)<td>
            <td>Header column 3 (150)<td>
        <tr>
    <thead>
    <tbody>
        <tr>
            <td>Body column 1 (150)<td>
            <td>Body column 2 (100)<td>
            <td>Body column 3 (150)<td>
        <tr>
    <tbody>
    <tfoot style="display:table-footer-group">
        <tr>
            <td>Footer column 1 (150)<td>
            <td>Footer column 2 (100)<td>
            <td>Footer column 3 (150)<td>
        <tr>
    <tfoot>
<table>

 

Use “table-layout:fixed” to make a statically-sized table (for speed), and use “colgroup” and “col” elements to provide the column sizes.  This makes the report render very quickly.  (No dynamic table sizing.)

Use “display:table-header-group” in the “thead” element, and “display:table-footer-group” in the “tfoot” element to make the header and footer appear on every page.

Try it!

XPath Performance in .NET

I continually hear people complaining about the performance of XPath queries in .NET, so I thought I would address it here.  Most of the time, the problem is that people are using the wrong classes.  (You know, with 6,000+ classes in .NET, I am always afraid that I will spend hours coding something just to find out that .NET provides it for free.)  So, the trick here is to use the correct class. Don't perform XPath queries against an XMLDocument or an XMLDataDocument. Use an XPathDocument instead.

Data Layer Sample:

' create a command object to run the stored procedure
Command = New SqlCommand("uspEmployeeListXML",Connection)
Command.CommandType = CommandType.StoredProcedure

' open the connection
Connection.Open()

' create xml read to acces the xml
XmlRdr = Command.ExecuteXmlReader()

' move to the first content node,
' bypassing any schema, comments, etc.
XmlRdr.MoveToContent()

' populate xml XPath document
XPathDoc = New XPathDocument(XmlRdr)

' return the document
Return XPathDoc

ASP.NET Code-behind Sample:

' obtain an XML XPath Document
myXPathDoc = Data.GetXPathDoc

' create a Transform object to represent the XSLT stylesheet
myTransform = New XslTransform()

' load the stylesheet into the object
myTransform.Load(Server.MapPath("~/ManualXSLT.xslt"))

' transform the XML directly to the page
myTransform.Transform(myXPathDoc,Nothing, Response.Output, Nothing)

In one of my tests, an HTML page that took 30 seconds to render with an XMLDocument took 3 seconds with an XPathDocument.

For more examples of this kind of code, refer to my presentation entitled “XSLT & XPath”, found on the Memphis .NET Users Group Presentation page.

.NET Game Programming

Have you ever wanted to program a game in .NET, but didn't know where to start?  I picked up a cool book recently that helped me do just that.  “.NET Game Programming with DirectX 9.0”, by Alexandre Santos Lobao and Ellen Hatton, teaches you how to get started programming games.

This book takes you through the entire development process, from the initial game proposal to the final product.  Along the way, many concepts are explained; graphics in general, GDI+, and Managed DirectX 9.0.  Yep, Managed DirectX 9.0.  I really enjoyed programming my first DirectX project using .NET.  No APIs required.

Games presented include a Tretris clone, a Snake clone, and a vertical scolling game similar to Atari's River Raid.  Very cool programming.