Category Archives: .NET

.NET breaking the LSP

Trying to implement cleaner than before, I noticed that it’s sometimes hard to do, especially if you allow .NET framework classes to be passed as arguments. Within just a few days, I stumbled upon the following base classes that do not respect the Liskov Substitution Principle (LSP):

A Stream in .NET has the CanRead, CanSeek and CanWrite methods. Depending on these properties, the Read(), Write() and Seek() methods may throw a NotSupportedException. If you have designed an API that takes a Stream as parameter, I can certainly break it by passing in a Stream that has no capabilities at all. There is no sort of contract between your API and the Stream that require it to be readable, writeable or seekable. But that’s exactly what LSP wants: a reliable contract.

Collections are similar to Streams, except they do not expose their capabilities, e.g. there’s no CanRemove property that a ReadOnlyCollection could set to false. As a result, the Remove() method throws a NotSupportedException, thus breaking your API’s implementation like the Stream did.

Bitmaps do not look dangerous at first, except that the owner might dispose it at any time. If however, you allow to change the format of the bitmap as used in the Save() method. Because some images formats are read-only and cannot be written. This is not documented on MSDN but in KB 316563. So, if you API accepts an ImageFormat, missing compliance of the .NET framework to the LSP may break your application again.

Visual Studio File Size Extension

I posted a Code Puzzle on StackExchange. When solving it myself in C#, I found out that it is hard to tell whether the latest refactoring made the file smaller or larger. Therefore I asked for a Visual Studio file size extension on Software Recommendations. Unfortunately, nobody answered, so I checked whether I could implement it myself.

Here it is, a small extension with no features except displaying the number of printable characters in the text buffer of the editor, measured correctly using StringInfo.LengthInTextElements().

License

The MIT License (see opensource.org)

Download

Code Golf File Size Visual Studio Extension 1.0.0.1 (11 kB)

The VSIX file is digitally signed for “Thomas Weller”. If not, please contact me.

Screenshot of Visual Studio File Size Extension installation

Screenshot of Visual Studio File Size Extension installation

File size extension in action

File size extension in action

Known bugs

Starting from 1.000.000 characters, the character count starts hiding under the editor’s scroll bar.

Processing Word documents with DocX

For an association, I had the task to write some Word documents to all members. Unfortunately, the task was a bit more complex than simply writing a circular letter and I decided to automate this task, because it will reoccur once a year.

Of course I started with the built-in Office automation which is part of Visual Studio 2010. However, I ran into deep trouble configuring all the security aspects. I was unable to open documents from a network location, because it is not trusted by default. Next I should have applied code signing in order to make it work. As I don’t have a valid certificate, this was the point in time where I was looking for alternatives.

And I found DocX at Codeplex. It really works like a charm! I didn’t have any security warning to solve, so that I’m confident it will run on other PCs as well without major administration work. It claims to work even on PCs without having Word installed. Second, the API is much more intuitive. You don’t have to deal with Type.Missing parameters and all this stuff. And the task of replacing text is done in one line of code instead of defining a range, executing a find query and then replacing the result.

Of course, DocX does probably not offer all features Word has. But it was definitely the best choice for me at this time to do a simple text replacement task (and some calculations in my code) to get the circular letter ready.

Generating PDFs with PDFSharp

PDFSharp (rev. 2013-01-06) is an open source library for creating PDF documents in any .NET language. I recently used this library because I had a print functionality in an application using the standard PrintDocument class of the Microsoft .NET Framework. The customer now wanted PDF support without the need of installing a PDF printer such as PDFCreator (rev. 2013-01-06), which would have been my first choice of realizing PDF support.

At first, I refactored the existing code with a lot of help of Resharper (rev. 2013-01-06), an invaluable tool for such tasks. The existing code parsed an XML description of what to print and directly sent it to the PrintDocument. I loosened this tight coupling and introduced a strategy pattern (rev. 2013-01-06) for printing to the PrintDocument. In the next step, I wanted to create another strategy for printing to PDFSharp. The step of defining the strategy interface and moving the PrintDocument implemention into the strategy went very well. The old functionality was not broken, so I could move on to the next step, learning about PDFSharp and doing some exercises.

At first glance, PDFSharp seemed to have all the features I needed and which were defined in the XML description: Rectangles and Pens for drawing them, Fonts and methods for drawing text. Of course, a Hello World program was the first to be achieved:

var page = new PdfPage();
page.Orientation = PageOrientation.Portrait;
page.Size = PageSize.A4;
var pdf = new PdfDocument();
pdf.Pages.Add(page);
var pageGraphics = XGraphics.FromPdfPage(page);
var arial = new XFont("Arial", 12.0);
pageGraphics.DrawString("Hello World", arial, XBrushes.Black, 10, 10, XStringFormats.Default);
pdf.Save(@"d:\sample1.pdf");

This worked very well and looked exactly like typing “Hello World” in Word and saving as PDF. I was glad, everything went smoothly so far.

When implementing the XGraphics.FromPdfPage(…) line, I saw that there was an overload where the units of the page can be specified. It also contains a definition for millimeter, which perfectly fits my needs. The definitions in my XML document are in millimeters and it took a while to implement all the conversions for the PrintDocument, so I was happy, PDFSharp would do all this for me. So I just changed the code to have

var pageGraphics = XGraphics.FromPdfPage(page, XGraphicsUnit.Millimeter);

However, this time, the text was way too big. Actually it looked like the font is now 12 millimeters high instead of 12 point. To check, what mistake I made, I read a bit more in the documentation. It turns out that the parameter of the XFont constructor actually wants to have the font size measured in em, not in pt.

This again means that I should have specified 1.0 em instead of 12.0 pt in my first example and that the output of the initial hello world program was already wrong. A quick check indicates that it was accidentally correct because the default unit is point:
var pageGraphics = XGraphics.FromPdfPage(page);
MessageBox.Show(pageGraphics.PageUnit.ToString());

Well, ok, if this is the only problem to work around, implementation will be about the same effort as for the PrintDocument. But the next problem didn’t wait long to pop up. The XGraphics.DrawString(…) method does not handle line breaks (newlines) as the .NET Graphics.DrawString(…) method does. Instead, PDFSharp will output something like blanks for \r and \n.

This is a little bit trickier to work around. You need an XTextFormatter, a XRect for the region which is available for the layouter and then call DrawString(…) on the formatter instead of the XGraphics object:

var formatter = new XTextFormatter(pageGraphics);
var layoutRectangle = new XRect(10, 10, page.Width, page.Height);
formatter.DrawString("Hello\r\nWorld", arial, XBrushes.Black, layoutRectangle);

This works and is not too complex to understand, but to use it corretcly, the page.Width and page.Height need to be replaced by some calculation which takes the page margins into account.

When implementing above layout mechanism, I saw that the formatter also has some properties which can be set.

var formatter = new XTextFormatter(pageGraphics);
var layoutRectangle = new XRect(10, 10, page.Width, page.Height);
formatter.Font = arial;
formatter.LayoutRectangle = layoutRectangle;
formatter.Text = "Hello\r\nWorld";

Unfortunately, there’s no method to draw the string without arguments, so this is quite useless. I thought it wouldn’t really matter to me, because I have a working solution for multiline strings.

Again, while using the XTextFormatter.DrawString(…) method, I saw that there’s an overload which takes a XStringFormats argument. This comes pretty handy, because I need to center a text as well. A short test should prove it works, before I use it in my code, so I simply added the XStringFormats.Center argument.

formatter.DrawString("Hello\r\nWorld", arial, XBrushes.Black, layoutRectangle, XStringFormats.Center);

I don’t exactly know how people use PDFSharp, but almost everything I try fails – also in this case. The function throws an ArgumentException saying that only TopLeft is implemented.

Implementing a multiline string center functionality is not so simple and it was worth googling for a solution. It quickly turns out that the XStringFormat argument of XTextFormatter.DrawString(…) is not the same thing as the XTextFormatter.Alignment property. Finally, I could use an Alignment of Center and keep the XStringFormat in its default to get centered text.

Well, finally it seems I have just went through all the problems during the Hello World phase. The final implementation of the PDFSharp strategy was completed within three hours.