Friday 3 April 2009

Official notification

Official Notification

As of 17th of February 2009, we received a request from Sage (UK) Limited to cease offering our SageDataObjects software without their consent. We have since stopped offering the SageDataObjects software component for sale.

As of the 5th of November 2011, we have also stopped offering our "Line 50" application for mobile phones. 


Sunday 1 February 2009

C#4, Dynamic Types and Sage

I was reading an article in this month's VSJ, and I was interested to read about C# 4.0's new Dynamic type. This type is C#'s answer to the weakly typed objects of languages like Basic, PHP, etc., This gives some advantages when dealing with .NET interfaces that lay above COM infrastructures, especially the Sage Data Objects library.

Therefore, with dynamics, code such as

SageDataObject50.InvoicePost InvPost;

InvPost = (SageDataObject50.InvoicePost)ws50.CreateObject("InvoicePost");

can become:

dynamic dInvoicePost = ws50.CreateObject("InvoicePost");

The cast to InvoicePost will be done at runtime, and the code will still compile, even if you don't know what the return object of this particular CreateObject method can be cast to.

The downside to this, as in every weakly typed language, is that many errors will not be spotted until runtime, and you may need to go through a process of trial-and-error to see what methods are available on a particular dynamic type.

According to VSJ this method for invoking COM objects should actually be more efficient, and certainly more elegant than using reflection.

Hopefully, I should be able to find a CTP download of C#4 to put together a code example.

Saturday 24 January 2009

Using COM reflection

I read with interest this month's MSDN magazine article on COM reflection. The article provides an example of using reflection to uncover hidden properties and methods of the Speech library, and also explains how the elusive System.__ComObject can give up its goodies, so to speak.

It works fine on the sample Speech API DLL on the site, however, it isn't so hot when it comes to Sage. I tried plugging in some common CLSID's from Sage's inner workings, but it gave up no further information. I then tried passing a System.__ComObject to it, with the following code;

Dim oUnknown As Object = o.GetCompanies("C:\Program Files\Sage\Accounts")
DumpCOMObject(oUnknown)

However, it crashed out when IDispatch::GetTypeInfoCount returned 0. According to MSDN reference this is done to prevent run-time inspection of the DLL, perhaps for security purposes.

So, I guess this is a bit of an anti-pattern when it comes to Sage development, but I hope that this research saves another developer some time when it comes to trying to figure out the million dollar question 'what do I cast this object to now?'