cameronfletcher.com

random thoughts and discussions on the things that interest me

Running Roslyn on a Build Server

If like the majority of people you shy away from installing a full blown copy of Visual Studio on your build server (for whatever reason) but you’d like to use it to compile using Roslyn then this can be achieved by following the advice given on this StackOverflow post. The steps I took were as follows:

1. Install the Roslyn End User Preview on the machine you use for developing.

2. Locate the following folder %userprofile%\AppData\Local\Microsoft\MSBuild\12.0

3. Copy the file Microsoft.CSharp.Roslyn.targets from \Microsoft.CSharp.targets\ImportAfter into C:\Program Files (x86)\MSBuild\12.0 on the build server into similarly named folders

4. Open up the file Microsoft.CSharp.Roslyn.targets and locate the element named RoslynToolPath and make a note of it’s value. This is the location of the compiler on your development machine.

5. Copy the contents of the folder containing the compiler onto the build server and place it them in a folder that is accessible from the security context under which the build process will be running.

5. Replace the RoslynToolPath in the Microsoft.CSharp.Roslyn.targets file on the build server with the path into which you have just copied the compiler.

6. Repeat for Microsoft.VisualBasic.Roslyn.targets if you want to build VB.NET using Roslyn too.

CQRS and when the Penny Dropped

I’ve been working on a project for a while now where the requirement is to provide a more scalable and better performing version of an existing system.

We chose to base the new system on Greg Young’s open-source SimpleCQRS project. Earlier this week I was refactoring one of the domain objects when I came across something like the following:

private string description;

public string Description
{
    get { return this.description; }
}

public void ChangeDesciption(string description)
{
    ApplyChange(new DescriptionChanged { Description = description });
}

private void Apply(DescriptionChanged @event)
{
    this.description = @event.Description;
}

I noted that the public Description property was unused, so I removed it.

Then the penny dropped.

I noticed that I could remove the private description property too because it was not used in any of the business logic. Then the previous sixteen lines of code became the following four:

public void ChangeDesciption(string description)
{
    ApplyChange(new DescriptionChanged { Description = description });
}

Less code. More sense. And a growing realisation that I had been confusing the responsibility of the GUI to display the description of the product with that of the domain object which was only concerned with business logic – something that the product description had nothing to do with.

InvalidOperationException: Dynamic operations can only be performed in homogenous AppDomain

Aaaah. Right. I didn’t expect that.

To set the scene, I’m writing a .NET 4.0 unit test in Visual Studio 2010 and using Microsoft Moles to test code that’s impossible to test (or something like that). My simplified unit test code can be found below.

using System.IO;
using System.IO.Moles;
using Microsoft.VisualStudio.TestTools.UnitTesting;

[TestClass]
public classFileWrapperTest
{
    [TestMethod, HostType("Moles")]
    publicvoid TestMethod1()
    {
        // arrange
        var fileWrapper = new FileWrapper();
        MFile.ExistsString = path => false;

        // act
        dynamic exists = fileWrapper.DoesExist(@"C:\temp\test.txt");

        // assert
        Assert.IsFalse(exists);
    }

    public classFileWrapper
    {
        public bool DoesExist(string path)
        {
            return File.Exists(path);
        }
    }
}

I’ve added a Moles assembly for mscorlib to the project and the following to AssemblyInfo.cs:

using Microsoft.Moles.Framework;
[assembly: MoledType(typeof(System.IO.File))]

I run the test and bang, InvalidOperationException: Dynamic operations can only be performed in homogenous AppDomain. Now – because of the lack of complexity in the simplified code – you may have spotted the cause. Why, you will be asking, has the boolean “exists” been declared as dynamic? Well… simply in order to illustrate the point (the test would work otherwise)! The DLR bombs if you attempt a dynamic operatioon, specifically System.Runtime.CompilerServices.CallSiteBinder .BindCore(CallSite site, Object[] args) with (thanks to Reflector) this little gem:

if (!AppDomain.CurrentDomain.IsHomogenous)
{
    throw Error.HomogenousAppDomainRequired();
}

Now, I know that the AppDomain should be homogenous when running in Full Trust following the overhall to CAS has had in .NET 4.0 (more here) and as that’s what I’m coding in why isn’t it? Well, it turns out that when you host an MS Test inside a Moles test host that the AppDomain that is created for the test is not homogenous. And that’s it. I’m not sure what to do next? I’ve posted in the forums and sent an email to Microsoft but not had a real reponse yet. I guess I’ll just need to be aware that I can’t use the DLR inside of a Moles test host.

Tackling Code Reviews using Automation

I’m currently undertaking a QA exercise on outsourced code as it gets delivered. In order to increase the productivity of the review process by reducing the defects raised and number of iterative fix cycles, I have been involved in writing tools that can be used by the external developers for them to check for compliance with specific coding standards and techniques demanded by the business.

The tools I am using for this automation are StyleCop and FxCop, Microsoft’s free code styling and managed code analysis tool. A great number of the standards we have defined are covered by the default rules that ship with these tools but there have been exceptions. For instance, we do not expect any TODO comments in code that has been delivered.

There are several detailed tutorials covering how to write these rules so I’m not going to repeat what’s already out there (links below).

http://scottwhite.blogspot.com/2008/11/creating-custom-stylecop-rules-in-c.html
http://www.lovethedot.net/2008/05/creating-custom-rules-for-microsoft.html (3 parts)

The code for my TODO rule is below. You simply need to call this method from one of the visitor callbacks mentioned in the above posts.

private static void FlagViolationForToDoComment(
    SourceAnalyzer analyzer,
    CsElement element)
{
    var todoComments = element.ElementTokens
        .Where(e => e.CsTokenType == CsTokenType.SingleLineComment ||
            e.CsTokenType == CsTokenType.MultiLineComment)
        .Where(c => c.Text
            .Substring(0, c.Text.Length >= 10 ? 10 : c.Text.Length)
            .Contains("TODO"));
 
    if (todoComments.Any())
    {
        foreach (var comment in todoComments)
        {
            analyzer.AddViolation(
                comment.FindParentElement(),
                comment.LineNumber,
                CustomRules.ToDoCommentsShouldBeActionedThenRemoved);
            }
        }
    }
}

One of the things to watch for is that if you install StyleCop with the MSBuild plugin that StyleCop may reside in more than one folder with one instance being registered with Visual Studio, and the other with the Explorer shell. In order to update the rules for use with both you will need to copy your rules library into each installation folder; in my case:

C:\Program Files\Microsoft StyleCop 4.4.0.14
C:\Program Files\MSBuild\Microsoft\StyleCop\v4.4

There’s also a StyleCop contrib project that provides a test-runner allowing unit testing of your StyleCop rules. I can’t recommend this enough – in my mind the only way to write StyleCop rules is to use TDD.

File Transfer via Clipboard Text

I have recently been involved in some work that requires me to program on a Remote Desktop (via RDP over an SSL connection) so there is no development software installed locally. One of the downsides is that due to the restricted nature of the connection only text based copy and paste works, so it is not possible to transfer files onto the development environment. Not only this, but although the local machine has access to the internet, the development environment has none.

The solution? I wrote a console based application called MemCopy to copy files to and from the clipboard as text. It does this by either encoding the file as Base64 then saving it as text on the clipboard, or decoding it from the clipboard.

I’d only written this in one of the environments, so I had to decode it in the other before I could use it – a bit chicken and egg, if you ask me. Anyway, I have attached a link to the encoded text here (you didn’t think I was going to give you the solution on a plate did you?)

The code below is all that was required to decode it. I placed the encoding into the resources as a file.

byte[] buffer = Convert.FromBase64String(Resources.Encoding);
FileStream stream = new FileStream(
    "memcopy.zip", 
    FileMode.Create,
    FileAccess.ReadWrite);
BinaryWriter writer = new BinaryWriter(stream);
writer.Write(buffer);
writer.Close();

The result? Awesomeness.

Converting a CTE T-SQL Statement into Linq2Sql

Below is the SQL statement including the common table expression that I need to re-write using Linq2Sql for an application I’m working on. The query identifies the subset of most up-to-date records using a group by query in a CTE. It then performs a join back to the booking table to return the full list of most up-to-date records.What is noticeable about this particular piece of code is the join between table and CTE making use of the isnull keyword.

with cte (RootBookingID, CreatedTime)
as
(
    select
        isnull(ParentBookingID, BookingID),
        max(CreatedTime) -- get the latset version
    from [system].Booking
    where Deleted = 0
    group by isnull(ParentBookingID, BookingID)
)

select b.*
from [system].Booking b inner join cte
on cte.RootBookingID = isnull(b.ParentBookingID, b.BookingID)
    and cte.CreatedTime = b.CreatedTime;

When rewriting this in C#, we first declare the query for the CTE as its own variable.

//define the cte to use as an anchor
var cte = from b in this.Model.Bookings
    where b.Deleted == false
    group b by b.ParentBookingID ?? b.ID into g
    select new
    {
        BookingID = g.Key,
        CreatedTime = g.Max(b => b.CreatedTime)
    };

We can then reuse this variable within our core query (below). Notice how the join on isnull is created by explicitly defining the name of the anonymous type.

//perform a join on the cte to get the results
var qry = from b in this.Model.Bookings
    join c in cte
        on new
        {
            ID = (b.ParentBookingID ?? b.ID),
            b.CreatedTime
        } equals new
        {
            ID = c.BookingID,
            c.CreatedTime
        }
    order by b.PickUpTime
    select b;

The post here explains the stumbling blocks I encountered:

To join multi-valued keys you need to construct an anonymous type on both sides of the ‘equals’ that is the same type. The anonymous type initializer expression infers both type and name of members from the expressions that are supplied. Using the name = value syntax in the initializer you can specify the name the compiler uses when creating the type. If all members, types, and names are the same then the anonymous types are the same type.

Internal Interfaces

Occasionally there is the need to expose, for the purposes of an API or such like, a property of a class that has different external and internal implementations. Consider the code below: a person class with an Id property that is set to -1 by default with an external get property and an internal set property.

public class Person
{
    private int _id = -1; // default value

    public int Id
    {
        get { return this._id; }
        internal set { this._id = value; }
    }
}

If there are several classes that implement the Id property in this manner and there is a need to reference them through a common interface externally then implementing the following on each of the classes should be sufficient:

public interface IIdentifiable
{
    int Id { get; }
}

However, to reference these classes internally using the same common interface may be insufficient as it does not allow a call to the internal set property. Clearly it would not be efficient, or necessarily easy, to cast the classes to their individual types prior to making the call. One solution is to use a separate interface for internal operations; an interface with internal scope:

internal interface IIdentifiableInternal : IIdentifiable
{
    new int Id { get; set; }
}

Here, we implement the IIdentifiable interface and declare the Id property as new, effectively hiding its IIdentifiable implementation. We don’t reflect this in quite the same manner in our implementation of the IIdentifiableInternal interface on our class though. Instead, we explicitly implement the IIdentifiableInternal interface:

public class Person : IIdentifiableInternal
{
    private int _id = -1; // default value

    public int Id
    {
        get { return this._id; }
    }

    int IIdentifiableInternal.Id
    {
        get { return this._id; }
        set { this._id = value; }
    }
}

The external members of the class now include the public get method of the Id property, as does the public IIdentifiable interface. However, internally the class can be referenced using the IIdentifiableInternal interface which allows access to both the get and set methods of the property.

What has been demonstrated is how to take a number of classes with common members that have both public and internal scope and provide a means to reference them through a common interface, both internally and externally.

As a final point, if you have a linked library which you want to have access to the internal interfaces then you can use the following assembly attribute to expose internal to the specified assembly:

[assembly: InternalsVisibleTo("MyLibrary.InterfaceExample")]

Overridden method OnMeasureItem is not being invoked

I just ran into an issue when subclassing the ComboBox class whereby the OnMeasureItem method that I was overriding was not being called. I had set the DrawMode to OwnerDrawFixed in the constructor for my ComboBox which had in turn filtered through to the designer (non-default value). When I amended the value in the constructor to OwnerDrawVariable the change did not then filter through to the designer (no surprises there). The result being that my constructor had the following code:

this.DrawMode = DrawMode.OwnerDrawVariable;

However, this was clearly at odds with the designer. So in order to stop this occurring again, and to stop any modification of the DrawMode via the designer, I changed the line in the constructor of my ComboBox to reference the base like so:

base.DrawMode = DrawMode.OwnerDrawVariable;

I then added the DrawMode property with the new keyword to replace the base version (see below). You need to include the property setter as the designer will still try to assign a value to DrawMode.

[Browsable(false)]
public new DrawMode DrawMode
{
    get { return base.DrawMode; }
    set { }
}

After tidying up the designer code everything works like a dream.