LP on .NET

October 28, 2010

Public Key Extraction

Filed under: .NET,C#,Software Development — Larry Parker @ 9:34 am

Sometimes it’s necessary to obtain the public key of a signed assembly.  A good example is when using the InternalsVisibleTo attribute to make a signed assembly friends with another.  For example:

[assembly: InternalsVisibleTo("MyUnitTestAssembly, PublicKey=00240000 ... be0b6719c")]

Note that we need the full public key and not the shortened public key token.

But how do we get the public key that we need?  There are a couple of ways.

One way is to write some code that uses reflection to extract the public key from your assembly.  Here’s an example:

Assembly assembly = Assembly.LoadFrom(@"MyAssembly.dll");
AssemblyName assemblyName = assembly.GetName();
Byte[] key = assemblyName.GetPublicKey();
String keyString = BitConverter.ToString(key).Replace("-", "").ToLower();

This results in a string of lower-case hex digits that can be inserted into the above InternalsVisibleTo example (to the right of “PublicKey=”).

If you don’t feel like coding, you can use Microsoft’s sn.exe utility to get it for you.

The first step is to open up a Visual Studio command prompt and navigate to the directory containing your assembly.  Then enter the following:

sn –Tp <assembly>

For example:

image

Note that this displays both the full public key as well as the shortened public key token.  You’ll need to copy the public key from the console and format it accordingly.

Another approach is to use sn.exe to extract it from the strong name key file.  This requires that you first extract it to another file that will just contain the public key:

sn –p <infile> <outfile>

For example:

image

Now that the public key has been extracted to a file, we can display it on the screen:

sn –tp <infile>

image

So you have your choice on how to get at the public key.  Pick whichever works best for you.

October 27, 2010

Executing an Action on a Collection

Filed under: .NET,C#,Software Development — Larry Parker @ 9:53 am

When I need to iterate through a collection of items (e.g. an array or a list) I typically use the “foreach” keyword like this:

String[] citiesArray = { "New York", "Boston", "Chicago" };

foreach (String city in citiesArray)
    BookFlight(city);

This is a very straightforward and acceptable approach.

However, I often find myself thinking in a more functional way and would simply like to execute some action on each item in a collection.

We can actually do this on lists.  Continuing with the above example:

List<String> citiesList = citiesArray.ToList();

citiesList.ForEach(o => BookFlight(o));

The ForEach method is part of the List<T> class and executes an Action<T> delegate on each element in the list.

This is a nice succinct way to do it, but C# unfortunately does not let us do this out of the box on arrays.

A simple workaround is to write our own ForEach extension method for IEnumerable<T> (which arrays implement).  Here’s the code:

public static class EnumerableExtensions
{
    public static void ForEeach<T>(this IEnumerable<T> collection, Action<T> action)
    {
        foreach (T element in collection)
            action(element);
    }
}

Now we can call the ForEach method on our array, just like we did on our list:

citiesArray.ForEeach(o => BookFlight(o));

Since our extension method is for IEnumerable<T>, we can use it on any collection that implements IEnumerable<T>.  This includes dictionaries and most results from LINQ operators.

I would not recommend using this approach on anything that requires more than a simple call on each element.  Being succinct is nice, but sometimes it can decrease code readability and make debugging a bit harder.

But for a simple call on each element in a collection (like BookFlight in the example above), the ForEach extension method can be very handy.

October 21, 2010

Obtaining the Application’s Path and Executable Name

Filed under: .NET,C# — Larry Parker @ 8:09 pm

I came across some code today where the full path and executable name of the application was needed.  It was obtained like this:

String fullPath = Application.ExecutablePath;

The Application class is a Windows Forms class, so the project had a reference to the System.Windows.Forms assembly.

But this particular app was non-visual (it was a Windows service), so the above approach is a bit heavy since the Windows Forms assembly would get loaded into memory and remain there until the app terminated.

A leaner approach is to use the Assembly class found in the System.Reflection namespace.  This is in the mscorlib assembly, which is part of every .NET program.

String fullPath2 = Assembly.GetEntryAssembly().Location;

It’s important to use the GetEntryAssembly method and not GetCallingAssembly or GetExecutingAssembly, since those will not necessarily correspond to the application’s executable.

The only difference I noticed between the value returned by the above two approaches is the casing of the executable’s extension.  Application.ExecutablePath returned <info>.EXE, while Assembly.GetEntryAssembly().Location returned <info>.exe.  Aside from that the casing was the same.

Hope this helps.

October 20, 2010

Unit Testing Using Stubs

Filed under: .NET,C#,Software Development — Larry Parker @ 10:34 am

There’s been a lot of talk in the industry about using mocking frameworks for unit testing, and while I do think that these are useful I haven’t yet ventured down this highway.

What I’d like to blog about today is using stubs for unit testing.  Stubs and mocks are not the same thing, as Martin Fowler points out in this post.  A shortened version is that mocks verify behavior while stubs can verify both behavior and state.

I’m currently working on a project that extracts data from QuickBooks and converts it to an XML document that gets submitted to a host system.

The unit test I wrote needs to verify that I am creating the XML correctly (i.e. in the format that the host expects) for a given QuickBooks customer record.  Here’s the unit test code:

[TestMethod()]
public void ConvertCustomerToXmlTest()
{
    QbToXmlConverter target = new QbToXmlConverter();

    String customerId = "12345";
    String firstName = "Larry";
    String lastName = "Parker";
    String phone = "555-1212";

    CustomerRetStub customer = new CustomerRetStub();
    customer.CustomerID = new QBStringTypeStub(customerId);
    customer.FirstName = new QBStringTypeStub(firstName);
    customer.LastName = new QBStringTypeStub(lastName);
    customer.Phone = new QBStringTypeStub(phone);

    XElement customerXml = target.ConvertCustomerToXml(customer);

    Assert.AreEqual("Customer", customerXml.Name);
    Assert.AreEqual(customerId, customerXml.Attribute("CustomerNumber").Value);
    Assert.AreEqual(lastName, customerXml.Attribute("LastName").Value);
    Assert.AreEqual(firstName, customerXml.Attribute("FirstName").Value);
    Assert.AreEqual(phone, customerXml.Attribute("Phone1").Value);
}

This test creates a new customer instance, submits it to the ConvertCustomerToXml method (which is the method being tested), and verifies that the XML returned by the method contains the expected structure and content.

And the test passes!  🙂

The signature of the ConvertCustomerToXml method looks like this:

XElement ConvertCustomerToXml(ICustomerRet customer)

Note that the customer parameter is of type ICustomerRet, which is a QuickBooks interface.  This makes sense because we will ultimately get our data from QuickBooks, so we might as well pass the interface directly to our method.

But also note that the unit test above does not supply an ICustomerRet interface reference that came from a QuickBooks SDK call.  Instead, it passes an instance of a class called CustomerRetStub.  What is this?

The QuickBooks interfaces are COM-enabled interfaces, and the SDK only provides a single concrete class that can be instantiated, called QBPOSSessionManagerClass.  This is used to open up a connection to the QuickBooks database, establish a session, create a message set request, and finally send a request and receive back a response.

That’s quite a bit of work for a unit test and is actually a bit far away from what we really want to test, which is to simply transform an ICustomerRet interface reference into XML that the host can receive.

Furthermore, QBPOSSessionManagerClass requires an actual QuickBooks database to connect to, which is a heavy dependency for a unit test (and technically starts moving us out of the realm of unit testing and into integration testing).

The way around all of this is to create our own class that implements ICustomerRet and use that to create a test customer, and then pass that into ConvertCustomerToXml.  This is called a stub.

Here’s what the CustomerRetStub looks like:

public class CustomerRetStub : QBBaseStub, ICustomerRet
{
    #region ICustomerRet members
    ...
    public IQBStringType CustomerID { get; set; }
    public IQBStringType CustomerType { get; set; }
    public IDataExtRetList DataExtRetList { get; set; }
    public IQBStringType DefaultShipAddress { get; set; }
    public IQBStringType EMail { get; set; }
    public IQBStringType FirstName { get; set; }
    public IQBStringType FullName { get; set; }
    ... 
    #endregion
}

This essentially creates a bunch of properties that correspond to the ICustomerRet interface.  The ICustomerRet interface itself just defines getter properties, but our concrete class needs to provide setter properties as well so we can set the values in our unit test.

Note also that the properties themselves are QuickBooks interfaces, and I had to stub these out as well.

Creating the stubs took some work, but it wasn’t too bad with the help of Visual Studio’s macro feature.

It’s important to point out that these stub classes are exactly that – stubs.  They don’t provide the full functionality of the actual types being stubbed out, but instead just enough of what we need for our tests.

Now that we have the stubs, our test is easy.  I’ll show it again, this time with the stubs highlighted in bold:

[TestMethod()]
public void ConvertCustomerToXmlTest()
{
    QbToXmlConverter target = new QbToXmlConverter();

    String customerId = "12345";
    String firstName = "Larry";
    String lastName = "Parker";
    String phone = "555-1212";

    CustomerRetStub customer = new CustomerRetStub();
    customer.CustomerID = new QBStringTypeStub(customerId);
    customer.FirstName = new QBStringTypeStub(firstName);
    customer.LastName = new QBStringTypeStub(lastName);
    customer.Phone = new QBStringTypeStub(phone);

    XElement customerXml = target.ConvertCustomerToXml(customer);

    Assert.AreEqual("Customer", customerXml.Name);
    Assert.AreEqual(customerId, customerXml.Attribute("CustomerNumber").Value);
    Assert.AreEqual(lastName, customerXml.Attribute("LastName").Value);
    Assert.AreEqual(firstName, customerXml.Attribute("FirstName").Value);
    Assert.AreEqual(phone, customerXml.Attribute("Phone1").Value);
}

A running QuickBooks database was not needed for our test, and we were able to test out exactly what we needed; i.e. that our XML was formulated the way we expected based on an ICustomerRet interface reference being passed to the ConvertCustomerToXml method.

As an aside, if we did want to create a test that uses the QuickBooks database and the actual QBPOSSessionManagerClass QuickBooks class, we could do something like this:

[TestMethod()]
public void ConvertCustomerIntegrationTest()
{
    QbToCcConverter target = new QbToCcConverter();

    IQBPOSSessionManager sessionMgr = null;
    String qbConnStr = ConfigurationManager.AppSettings["MyConnectionString"];

    try
    {
        sessionMgr = new QBPOSSessionManagerClass();
        sessionMgr.OpenConnection("LPTest", "LPTest App");
        sessionMgr.BeginSession(qbConnStr);

        IMsgSetRequest request = sessionMgr.CreateMsgSetRequest(3, 0);
        ICustomerQuery custQuery = request.AppendCustomerQueryRq();
        IMsgSetResponse msgSetResponse = sessionMgr.DoRequests(request);
        IResponse response = msgSetResponse.ResponseList.GetAt(0);
        ICustomerRetList customers = response.Detail as ICustomerRetList;
        ICustomerRet customer = customers.GetAt(0);

        XElement customerXml = target.ConvertCustomerToXml(customer);

        Assert.AreEqual("Customer", customerXml.Name);
        Assert.IsNotNull(customerXml.Attribute("CustomerNumber").Value);
        Assert.IsNotNull(customerXml.Attribute("LastName").Value);
        Assert.IsNotNull(customerXml.Attribute("FirstName").Value);
    }
    finally
    {
        if (sessionMgr != null)
        {
            sessionMgr.EndSession();
            sessionMgr.CloseConnection();
        }
    }
}

As you can see, there’s a bit more involved for this type of test.  Also notice that the assertions just confirm that the XML contains something for the attribute values.  Unless we know exactly what’s in the QuickBooks db that we’re using for our test, we can’t really write a test that checks for specific values in the XML.

But stubs allow us to bypass all of this and just focus on testing the specific method we’re interested in.  And since we have control over the data we supply to the stubs in our test code, we can write better assertions against them.

October 19, 2010

Removing a Specific Instance of SQL Server 2008

Filed under: .NET,SQL Server — Larry Parker @ 9:16 am

I normally work with a couple of instances of SQL Server 2008.  This allows me to better isolate work I’m doing for different projects, and also lets me run different SQL editions on a single machine (e.g. Express, Developer).

Recently I wanted to delete an instance I no longer needed, but could not figure out how to do this.  The SQL Server setup menus apparently do not have a deletion option.

The solution was to go to Control Panel –> Add or Remove Programs, select Microsoft SQL Server 2008, click Change / Remove, and then select Remove from the next dialog.

From a user perspective this just doesn’t feel right because it seems that you’ll end up uninstalling the entire SQL Server product!  Fortunately, the SQL Server setup program is run and you’re prompted to remove a particular instance.

Not the greatest user experience, but it works nonetheless.

Here’s an excellent blog post on the topic.

Hope this helps.

October 11, 2010

Renaming Namespaces

Filed under: .NET,C#,Software Development,Visual Studio — Larry Parker @ 4:04 pm

Did you know that you can use Visual Studio’s refactoring feature to rename namespaces?  Just position the cursor over the portion of the namespace that you want renamed and press F2 (or right-click and select Refactor | Rename), and Visual Studio will rename all occurrences of the namespace in your solution.

For example, from this (place the cursor somewhere over “Server”):

namespace MyApp.Server
{
    // ...
}

to this (after renaming to “Client” in the Rename dialog box):

namespace MyApp.Client
{
    // ...
}

Pretty handy feature!

Blog at WordPress.com.