Sometimes the appropriate response to reality is to go insane - Philip K Dick RSS 2.0
 Wednesday, March 26, 2008

Prompted by a discussion on the altdotnet yahoo group ... why I like broken builds ...

Some people try desperately to avoid breaking the build, by doing very infrequenet check ins (the number of broken builds per day drops dramatically, the time to fix each goes up though), or by trying to ensure their development environment is as close to the build environment as possible.

But a broken build is not a problem - it is an opportunity. A broken build allows you to identify a weakness, and to resolve it early.

The weakness might be in your architecture, it may be in your dependencies, or in your assumptions, or in your developer skill levels - but the whole point of having a continuous integration server is to fail fast and let you deal with the underlying problems rather than the specifics of the code you checked in.

 

Wednesday, March 26, 2008 9:14:57 AM (GMT Standard Time, UTC+00:00)  #    Comments [4] -
.NET | Agile | alt.net | C# | Continuous Integration | Design | Development
 Thursday, March 20, 2008

I've done it before, but my mind went totally blank yesterday ... due to some typically quick responses from the Castle Users Google Group ... here is the code to do it for future generations to avoid my same silly mistakes ...

WindsorContainer container = new WindsorContainer(); 
Type eventBrokerServiceType = typeof(IEventBroker<>); 
Type brokerType = typeof(EventBroker<>); 
container.AddComponent("key", eventBrokerServiceType, brokerType); 

IEventBroker<EventArgs> eventBroker = container.Resolve<IEventBroker<EventArgs>>(); 
Assert.IsNotNull(eventBroker); 


Thursday, March 20, 2008 9:44:12 AM (GMT Standard Time, UTC+00:00)  #    Comments [0] -
alt.net | C# | Castle | Sample Code
 Thursday, January 17, 2008

Previously I got my basic interception going, to allow me to strongly type resource requests.

The next step was to allow me to inject that capability via Windsor. The test for this was a bit tricky, due to me not understanding the Windsor container syntax in C#, but after a bit of playing around, we end up with the following code to create my IResource via the container.

    [TestFixture]
    public class SpikeProxyResources
    {
        [Test]
        public void TestWithFactoryCreation()
        {
            IWindsorContainer container = new WindsorContainer();
            FactorySupportFacility facility = new FactorySupportFacility();
            container.AddFacility("factory.support", facility);
            facility.AddFactory<IResource, ResourceFactory>("ResourceFactory", "CreateResource");

            IResource resource = container.Resolve<IResource>();
            Assert.AreEqual("GetVal", resource.GetVal);
            Assert.AreEqual("NewValue", resource.NewValue);

        }
    }

    public class ResourceFactory : IInterceptor
    {
        public IResource CreateResource()
        {
            ProxyGenerator generator = new ProxyGenerator();
            IResource proxy = generator.CreateInterfaceProxyWithoutTarget<IResource>(this);
            return proxy;
        }

        public void Intercept(IInvocation invocation)
        {
            if (invocation.Method.Name.StartsWith("get_"))
            {
                //TODO: Lookup resource here.... 
                invocation.ReturnValue = invocation.Method.Name.Substring(4);
            }
            else
                invocation.ReturnValue = null;
        }
    }

The next step will be to pull this configuration out into Xml ... or if I can convince the people that matter, into Binsor and Boo!

Thursday, January 17, 2008 5:43:55 PM (GMT Standard Time, UTC+00:00)  #    Comments [0] -
.NET | C# | Development | Sample Code
 Monday, December 03, 2007

I am pleased to say, not only do I have a full working Model-View-Presenter implementation running within a SharePoint WebPart now, but I am very very close to having the rendering abstracted away from the WebPart and into a UserControl too. I'll blog more about this when I'm happy with the whole solution end to end.

In the meantime however, one annoying problem got me very very confused for a while ... if only SharePoint didn't give such stupid error messages and let you debug it properly, my life would have been much easier ... It was silly mistake really ... would have found it in 30 seconds in an ASP.NET application ... anyway I digress.

Remember, if you are using Castle Windsor from the GAC (as you need to for SharePoint work), then the web.config entry must specify the stong name of the assembly in the ConfigSections entry:

<section name="castle" 
type="Castle.Windsor.Configuration.AppDomain.CastleSectionHandler,
Castle.Windsor, Version=1.0.3.0,
Culture=neutral, PublicKeyToken=407dd0808d44fbdc" />

I had copied and pasted the entry from another project, not in the GAC, it only had the entry as Castle.Windsor and voila I got a lot of cryptic errors from SharePoint.

As a secondary note, remember all of your entries in the <castle> section must also specify the strong name, or they too will give you cryptic messages and a lot of wasted effort.

Another one to watch out for!

Monday, December 03, 2007 1:39:10 PM (GMT Standard Time, UTC+00:00)  #    Comments [1] -
C# | Castle | Development | rants | Sample Code | SharePoint
 Friday, November 30, 2007

I have my MVP project coming along nicely, unit tests all running, presenters and interfaces doing their basic stuff. The assemblies are all being stongly named for SP deployment (into the GAC). Then I add my WebPart and implement IView on it.

Problem Numer 1 : Implementing an Interface on a WebPart using VSeWSS Causes Deploy to Fail

Oh yeah, that was fun. For speed and as I am working on a VM, I used the VSeWSS extensions to quickly create and deploy the web part. An hour later wasted, I pin down a problem with the Deploy command the Visual Studio extension provide. Just implementing an interface on the WebPart class causes the Deploy to fail - with a cryptic message about a reflection error.

Well done guys, I guess you are trying to find something that implements WebPart and nothing else? Whatever the reason, VSeWSS gone for good from my machine, I'm going back to doing this the hard way, where at least I have some control.

Problem Number 2 : The GAC ... "I'm not lying. Take my pen, write this down. Do not trust her."

So, my WebPart is now working, and all seems happy. With the assemblies deployed, I can now view my WebPart in all it's glory displaying "Hello World" with data coming from my repository via the presenter. All is good. All is level. All is pretty.

Then I do a bit of basic refactoring. Following some suggestions from ALT.NET people, I play around with my event signatures, remove out 'object sender' as this will be provided to the presenter on construction, and define an EmptyEventHandlerArg.

All pretty simple stuff. Hit build, all compiles just fine first time. Run all unit tests ... whoa there donkey...

System.InvalidOperationException: You have called the event raiser with the wrong number of parameters. Expected 1 but was 0
at Rhino.Mocks.Impl.EventRaiser.AssertMatchingParameters(MethodInfo method, Object[] args)
at Rhino.Mocks.Impl.EventRaiser.Raise(Object[] args)

Surely some mistake. Go over all code. Try to figure out if my usage of Rhino Mocks is wrong. Nope - all is correct, the IEventRaiser is being called correctly with the right number of parameters. The correct number of parameters in the view and the presenter.

Try this a dozen time more. Can't figure out why this worked just fine in my first prototype project where I had damn near the same code, so go back to that project. It all works just fine there. Change the signature there. It works just fine.

Back to my WebPart project. Stare blankly. Drink more coffee. Spark of inspiration ...

Delete the previous built assembly from the GAC. Now it all runs just fine.

It seems that the unit tests/Rhino are getting their references from the GAC, where as my projects are getting their reference from the build directory. On a machine where the assembly is built, but may also be in the GAC this is an issue for unit tests.

Off to try and find an explanation or solution. Of course I can copy to the GAC every build ... but I'm not sure I want to ... and I don't think it is healthy to have to ...

Friday, November 30, 2007 10:59:34 AM (GMT Standard Time, UTC+00:00)  #    Comments [0] -
C# | Development | SharePoint | Testing
 Thursday, November 29, 2007

Jean-Paul has updated his test naming macro to deal with class names as well as method names, and while I like naming my tests in the form of Test_That_Data_Has_Been_Loaded, I find that JP's macro doesn't work well for me.

The reason is that as I type in the form JP does ("Test That Data Has Been Loaded") I find ReSharper kicks in and start inserting class names for me. I have also got in the habit of typing "TestThatDataHasBeenLoaded" which is a lot less readable than JP's convention.

So I took JP's macro and modified it for my own use ... it will now turn my style of typing into JP's style of naming... voila ... readable test names!

TestThatDataHasBeenLoaded  ==>>  Test_That_Data_Has_Been_Loaded

Code below - all credit to JP for the bulk of this (and I am no VB programmer so my changes are pretty poorly coded, no critique needed pls):

Imports System
Imports System.Windows.Forms
Imports EnvDTE
Imports EnvDTE80
Imports System.Diagnostics
Imports System.Text.RegularExpressions

Public Module CodeEditor

    Sub ReplaceSpacesInTestNameWithUnderscores()

        If DTE.ActiveDocument Is Nothing Then Return
        Dim wrCS As Boolean = DTE.Properties("TextEditor", "CSharp").Item("WordWrap").Value

        Try
            DTE.Properties("TextEditor", "CSharp").Item("WordWrap").Value = False
            Dim selection As TextSelection = CType(DTE.ActiveDocument.Selection(), EnvDTE.TextSelection)
            Dim index As Integer

            selection.SelectLine()
            If selection.Text = "" Then Return

            Dim methodIndex As Integer = selection.Text.IndexOf("public void ")
            Dim classIndex As Integer = selection.Text.IndexOf("public class ")

            index = CType(IIf(methodIndex >= 0, methodIndex, classIndex), Integer)

            Dim prefix As String = CType(IIf(methodIndex >= 0, "public void ", "public class "), String)
            prefix = selection.Text.Substring(0, index) + prefix
            Dim description As String = selection.Text.Replace(prefix, String.Empty).Trim
            Dim r = New Regex("[A-Z][^A-Z]*")
            Dim myMatches As MatchCollection
            Dim reformedDescription As String

            myMatches = r.Matches(description)
            Dim successfulMatch As Match
            For Each successfulMatch In myMatches
                reformedDescription = reformedDescription + successfulMatch.Value + "_"
            Next
            reformedDescription = reformedDescription.Trim("_")

            selection.Text = prefix + reformedDescription + vbCrLf
            selection.LineDown()
            selection.EndOfLine()
        Catch ex As Exception
            MsgBox(ex.Message)
        Finally
            DTE.Properties("TextEditor", "CSharp").Item("WordWrap").Value = wrCS
        End Try
    End Sub
End Module
Technorati Tags: ,,
Thursday, November 29, 2007 11:55:29 AM (GMT Standard Time, UTC+00:00)  #    Comments [0] -
.NET | C# | Development | Sample Code | Testing

There is a really cool video, showing the power of ReSharper in the hands of a keyboard wizard ... but recently it went missing from the blog post in which it was first mentioned.

But, after a desperate plea, it is back in a new location http://www.jetbrains.com/resharper/documentation/index .html 

Watch it, learn from it, speed up your coding today

Thursday, November 29, 2007 10:52:00 AM (GMT Standard Time, UTC+00:00)  #    Comments [0] -
C# | Development | ReSharper
 Sunday, November 18, 2007

The interfaces we have created in Abstracting SharePoint allow us to unit test our code, but only if we mock the objects. We can do this in 2 ways, we either write an implementation of our own that mimics the SharePoint model (by storing data in in-memory objects for example), or we can use a mocking framework like Rhino Mocks or TypeMock.NET

My first approach was to write my own mock of SharePoint. This, I reasoned to myself, would allow me to actually setup test data, and to use the mocked layer to operate as a way of demonstrating the system in addition to testing.

This approach soon became a nightmare, the SharePoint object model is convoluted and confused. The interactions between objects are unclear, and often unexpected. I gave up on this one after a few hours of work that convinced me I needed to go down the other route.

For mocking I had a range of mocking frameworks to choose from, but Rhino Mocks (which I have used before with great success) was the obvious choice. Rhino has one limitation though which made me consider an alternative, it cannot mock Sealed classes. The bright sparks that wrote Microsoft.SharePoint decided the classes would be sealed, so although I can use Rhino to mock my newly formed interfaces, I would not be able to use it to mock Microsoft.SharePoint classes should the need arise (for example if it becomes too complex to complete the interface abstractions).

TypeMock.NET can, I am told, mock sealed classes. This would make it an ideal candidate for dealing with SharePoint. It is however a commercial product, and a pricey one at that. Cost isn't really a major issue here, but still it is a factor. It is also somewhat trickier than Rhino to get to grips with, at least for someone that has only just got to grips with the simpler aspects of Rhino.

For the present I am going to use Rhino, and I am going to hope I do not have to mock any sealed classes. If I do then TypeMock.NET may save me, but I suspect at that point I am in deeper trouble anyway. The two syntaxes are different enough that the learning curve is probably not worth it until I hit those 'sealed class' cases.

The Rhino Mocks version:

        [TestMethod]
        public void TestLookupUniqueItemReturnsSingle()
        {
            MockRepository mocks = new MockRepository();
            ICustomSPQuery query = mocks.CreateMock<ICustomSPQuery>();
            ICustomSPList list = mocks.CreateMock<ICustomSPList>();
            ICustomSPListItemCollection expectedResults = mocks.CreateMock<ICustomSPListItemCollection>();
            ICustomSPListItem listItem = mocks.CreateMock<ICustomSPListItem>();

            int numberOfResultsToReport = 1;

            With.Mocks(mocks).Expecting(
                delegate
                    {
                        using (mocks.Unordered())
                        {
                            Expect.Call(query.Query).PropertyBehavior().IgnoreArguments();
                            Expect.Call(list.GetItems(query)).IgnoreArguments().Return(
                                expectedResults);
                            Expect.Call(expectedResults.Count).Return(numberOfResultsToReport).
                                Repeat.Any();
                            Expect.Call(expectedResults[0]).Return(listItem);
                        }
                    })
                .Verify(
                delegate
                    {
                        ListLookup lookup = new ListLookup(list, query);
                        ICustomSPListItem lookupResult = lookup.LookupUniqueItem("test", "test");
                        Assert.AreEqual(listItem, lookupResult);
                    }
                );
        }

And the TypeMock.NET version:

        [TestMethod]
        public void TestSingleItemFindsMatch()
        {
            MockManager.Init();
            ICustomSPList list = (ICustomSPList)RecorderManager.CreateMockedObject(typeof(ICustomSPList));
            ICustomSPQuery query = 
               (ICustomSPQuery)RecorderManager.CreateMockedObject(typeof(ICustomSPQuery));
            ICustomSPListItemCollection expectedResults = (ICustomSPListItemCollection)RecorderManager
                .CreateMockedObject(typeof(ICustomSPListItemCollection));
            ICustomSPListItem item = 
                (ICustomSPListItem)RecorderManager.CreateMockedObject(typeof(ICustomSPListItem));

            using (RecordExpectations recorder = new RecordExpectations())
            {
                query.Query = "";
                recorder.ExpectAndReturn(list.GetItems(null), expectedResults);
                recorder.ExpectAndReturn(expectedResults.Count, 1).RepeatAlways();
                recorder.ExpectAndReturn(expectedResults[0], item);
            }

            ListLookup listToLookup = new ListLookup(list, query);
            ICustomSPListItem result = listToLookup.LookupUniqueItem("FieldName", "MyValue");
            Assert.AreEqual(item, result);
            MockManager.Verify();
        }

There is one more point in favour of Rhino Mocks ... its author Oren Eini (known as Ayende) is possibly one of the most talented developers I know, has a real passion for good quality code, and a deep commitment to open source and providing great tools to other developers. That alone makes Rhino an excellent choice.

Fingers crossed!

 

Sunday, November 18, 2007 7:25:31 PM (GMT Standard Time, UTC+00:00)  #    Comments [7] -
C# | Design | Development | Sample Code | SharePoint | Testing

I've been trying to work out in my head how I can deal with SharePoint in an abstracted a way as possible on my current projects. Frankly the interfaces MS provided were less than useful, or to be precise, not only did they forget to include any interfaces, but they also decided to make all their classes sealed too (*). I'm sure there are more unfriendly things they could do to developers writing SharePoint code, but I'm struggling to think of anything right now.

* Edit 29/11/2007 - just pointed out to me, that 'all their classes sealed' was a bit of a generalisation (and me ranting and fuming). Actually only a few key ones are sealed, but they do have a habit of having no default constructors, have no interfaces, and frankly are damn impossible to mock properly (TypeMock.NET excepted) ... hence the need for all this stuff.

So my thinking at present is along the lines of "I'm gonna write me a whole damn abstraction layer to SharePoint, because it has to be faster than coding against SharePoint directly and dealing with lack of unit testing and any kind of decoupling"

The Interfaces

The first step was to start creating interfaces that mimicked the Microsoft.SharePoint API:

image

This was pretty much the minimum number of interfaces I had to create, and I expect many more. This set will let you do basic list operations, but for anything beyond that, expect a lot more typing (or cheat and use ReSharper to extract the interfaces from your decorated SP classes)

A typical interface looks like:

    public interface ICustomSPList
    {
        ICustomSPListItemCollection Items { get; }
        ICustomSPListItemCollection GetItems(ICustomSPQuery query);
    }

This is a BIG task. A REALLY BIG TASK! So my first steps were to only abstract the classes, properties and methods I was using in the first few tasks of the overall project. Obviously this reduces the up-front work considerably, but I am crossing my fingers that it doesn't hide a nasty problem down the line. I'm pretty sure MS has done something really dumb somewhere to prevent this working, but so far so good.

The Decorators

Then there was a need to create decorators for each of the SharePoint objects we are abstracting, and delegating all calls through to the Microsoft.SharePoint classes:

The decorator class for the ICustomSPList looks like this:

    public class CustomSPList : ICustomSPList
    {
        private readonly Microsoft.SharePoint.SPList _list;

        public ICustomSPListItemCollection Items
        {
            get { return new CustomSPListItemCollection(_list.Items);}
        }
        public CustomSPList(Microsoft.SharePoint.SPList list)
        {
            _list = list;
        }

        
        public ICustomSPListItemCollection GetItems(ICustomSPQuery query)
        {
            Microsoft.SharePoint.SPQuery tempQuery = new Microsoft.SharePoint.SPQuery();
            tempQuery.Query = query.Query;
            return new CustomSPListItemCollection(_list.GetItems(tempQuery));
        }
    }

Basic Usage

We now have a basic way to perform SharePoint operations without being tied into the Microsoft.SharePoint dependency:

    ICustomSPWeb web = properties.OpenWeb();
    ICustomSPList registryList = web.Lists["Registry"];
                    
    ICustomSPQuery query = new SPQuery();
    query.Query = "<Where><Eq><FieldRef Name='Title' /><Value Type='Text'>My Title</Value>
                   </Eq></Where>";

    ICustomSPListItemCollection regList = registryList.GetItems(query);

The Next Step

We have our basic abstraction in place now, and with a little magic from an IoC container like Windsor we can write the core of our application safe in the knowledge that we aren't heading down a dead end of a coupled system. We also have a system that, although it is using the SharePoint API, could be switched to a different persistence medium should the need arise.

But that is only half the story, and in fact the really important part ... we can now properly mock and unit test our code.

 

Sunday, November 18, 2007 7:12:47 PM (GMT Standard Time, UTC+00:00)  #    Comments [1] -
.NET | C# | Design | Development | SharePoint | Testing
 Wednesday, August 01, 2007

This is a repost from my old blog, as it is code I'm bound to need again sometime...

More than once I have needed to sort items according to some arbitrary sort criteria, for example to sort a list of  status codes. They can't be logically sorted alphabetically, so I wrote these routines.

In the example, it is a string list, but it could be any object with a bit of modification. Essentially this uses a Comparer, which uses the position within the SortString to decide on the order of the items. Nice and simple.

List<string> MyList = new List<string>();
MyList.Add("OK");
MyList.Add("Failed");
MyList.Add("Stopped");
MyList.Add("Beginning");
SortStringList(MyList, "Beginning;OK;Failed;Stopped;");
        private void SortStringList(List<string> list, string sortString)
        {
            if (string.IsNullOrEmpty(SortDirection))
                list.Sort(new StringListComparer(sortString));
            else
            {
                StringListComparer.SortDirection direction;
                try
                {
                    direction =
                        (StringListComparer.SortDirection)
                        Enum.Parse((typeof(StringListComparer.SortDirection)), SortDirection);
                    list.Sort(new StringListComparer(sortString, direction));
                }
                catch(ArgumentException ex)
                {
                    throw new ArgumentException(
                        string.Format("An attempt was made to parse the 
SortDirection key ('{0}')
which did not evaluate
to a known value
", SortDirection), ex); } } }
    public class StringListComparer : IComparer<string>
    {
        public enum SortDirection
        {
            Ascending,
            Descending
        }

        private SortDirection _sortDirection;
        private string _sortString;

        public StringListComparer(string sortString)
            : this(sortString, SortDirection.Ascending)
        {
            
        }
        
        public StringListComparer(string sortString, SortDirection direction)
        {
            if (sortString == null)
                _sortString = string.Empty;
            else
                _sortString = sortString;

            _sortDirection = direction;
        }

        public int Compare(string x, string y)
        {
            if (x == null || y == null)
                return EvaluateForNullStrings(x, y);
            else
                return EvaluateForNonNullStrings(x, y);
        }

        private int EvaluateForNonNullStrings(string x, string y)
        {
            int indexOfX = _sortString.IndexOf(x) + 1;
            int indexOfY = _sortString.IndexOf(y) + 1;

            if (indexOfX == 0 && indexOfY != 0)
                return (_sortDirection == SortDirection.Ascending) ? -1 : 1;
            else if (indexOfX != 0 && indexOfY == 0)
                return (_sortDirection == SortDirection.Ascending) ? 1 : -1;
            else
                return (_sortDirection == SortDirection.Ascending)
                           ?
                       indexOfX.CompareTo(indexOfY)
                           :
                       indexOfY.CompareTo(indexOfX);
        }

        private int EvaluateForNullStrings(string x, string y)
        {
            if (x == null && y != null)
            {
                return (_sortDirection == SortDirection.Ascending) ? -1 : 1;
            }
            else if (x != null && y == null)
            {
                return (_sortDirection == SortDirection.Ascending) ? 1 : -1;
            }

            return 0;
        }
    }
 
Technorati Tags: , , ,
Wednesday, August 01, 2007 4:53:26 PM (GMT Standard Time, UTC+00:00)  #    Comments [0] -
.NET | C# | Development | Sample Code
Navigation
Archive
<July 2008>
SunMonTueWedThuFriSat
293012345
6789101112
13141516171819
20212223242526
272829303112
3456789
About the author/Disclaimer

Disclaimer
The opinions expressed herein are my own personal opinions and do not represent my employer's view in any way.

© Copyright 2008
Casey Charlton
Sign In
Statistics
Total Posts: 41
This Year: 13
This Month: 0
This Week: 0
Comments: 27
Themes
Pick a theme: