Welcome to MSDN Blogs Sign in | Join | Help

Guidance on SharePoint

You all might be amazed by the number of emails, messages, and calls I get asking for any of the following:

  • Guidance on SharePoint
  • Requests to add SharePoint Guidance to WCSF
  • Requests to add "Office applications" support to SCSF

Well, I can finally help out folks looking for guidance on how to build SharePoint applications by saying "go check out the CodePlex project for patterns & practices SharePoint Guidance (http://www.codeplex.com/spg)."  If you are hoping for SharePoint support in WCSF, you should probably check this out too.

Blaine and Francis are leading the effort on this project.  I understand that they are tackling a few big challenges that customers have ranked as the most important including (this list is from the project's Vision Scope slide deck):

  • Unit testing and debugging
  • Packaging and deployment
  • Setting up a team development environment
  • Unclear which SharePoint features/ components to use and when
  • Solution maintenance/upgrade
  • How and when is SharePoint Designer applicable

If you do SharePoint development, you should check it out.

See Real Results With patterns & practices

I visited the p&p homepage on MSDN today, and saw an announcement for a research report by Nucleus Research about patterns & practices, and what companies that use our guidance think the benefits are.  Check out See Real Results With patterns & practices (an overview) and download and read the full report.  As a member of p&p I thought it was informative and showed a few areas that we can improve.  It also showed areas where customers have reaped big benefits from using p&p deliverables, which I would be interested in if I were "out in the real world" and looking to re-use one of the p&p application blocks or an open source alternative.  To borrow a few lines from the report:

"THE BOTTOM LINE
Companies use Microsoft patterns and practices to make their development environments more productive, consistent, and standardized.  Whether used by an independent software vendor, consultancy, or enterprise, patterns and practices can accelerate project cycle times, reduce costs, and shift application development efforts away from code building and toward maximizing business benefits."

-- Guidebook: Microsoft patterns & practices, Nucleus Research Inc., April 2008,
http://www.microsoft.com/downloads/details.aspx?FamilyId=3696068D-BE4A-4731-AB15-492377AA4C6D&displaylang=en

Enjoy.

Acceptance Testing Guide Community Preview 2 Available!

As I have mentioned before in a few posts (Acceptance Test Engineering Guidance, Acceptance Testing Guidance Survey, and Acceptance Testing Guide Update), I am working with a team on guidance around acceptance testing.  We still have a lot of work to do our the guide, but we have made available a second community preview to show you how things are shaping up and to give you a chance to provide feedback.

Check these out:

Composite Application Guidance for WPF Shipped!

A while back, I was Dev Lead on the Smart Client Software Factory (SCSF) when we added the ability to host WPF controls in a Composite Application Block (CAB) application. Since then, the thinking in the WPF space has changed a bit, and p&p decided that offering guidance on full WPF applications was a good idea.  Blaine, Francis, Bob, and Glenn have worked with a great team to create guidance for building composite applications using WPF. This guidance was started from a clean slate, as there are enough differences between Windows Forms and WPF (as we learned doing SCSF) to cause challenges.  The result is the Composite Application Guidance for WPF June 2008, which recently shipped (formerly code-named Prism).  This guidance is simple, easy to consume, can be used piecemeal, and should not have the steep learning curve that CAB and SCSF have.  You can learn more at the Prism CodePlex Community Site, or at any of the places below. 

Check out Francis's post, SHIPPED!!! Composite Application Guidance for WPF June 2008, for details and where to get it.

Or take a look at Glenn's post on the subject: Composite Application Guidance is Live

And here are a few other posts about what they have been up to, by person in chronological order:

From Francis:

From Blaine:

From Glenn:

I know I am looking forward to using this guidance when I get a chance to work with WPF more seriously.

Enjoy.

Proof of Concept: a simple DI solution for ASP.NET WebForms

Chris Tavares and I were chatting yesterday morning about an idea Chris had: building a simple, reusable Http Module that gives folks DI scoped to the Application, Session, and Request.  Yesterday afternoon, during the p&p Dev team's weekly "Code Kata" we threw together a spike/proof of concept in a couple of hours.  "Code Kata" is a three hour block of time that the p&p Dev team uses for a number of things:

  • cross-project pollination of ideas, things that work, things that don't work across project teams
  • investigating new and emerging technologies that p&p may work with in the future
  • investigating new and emerging platforms to determine if p&p may want to provide guidance in the future
  • play with new shiny bits :-)

There are no unit tests, just simple acceptance tests written as a really simple web site.  If the site works and shows the right text, the test passes.  We started with a list of requirements (scaled to just the application level) on the whiteboard that looked sort of like this (which I am creating from memory):

  • Create a DI container for the application
  • Create a way to get to the container ( we choose an extension method on the Application class)
  • Allow a way to configure the container
  • Allow DI to work for pages
  • Allow DI to work for user controls
  • Allow DI to work for master pages
  • Allow DI to work for ASMX web services
  • Allow the above functionality in a simple and self contained way

So, we created a simple Web Site Application and a DLL to hold the custom HttpModule.  We created a simple web page that needed a property injected into it.  We then wrote the code to make my "test" page work properly.  First we wrote an extension method for HttpApplication.  After a short bit it changed to one for HttpApplicationState:

using System.Web;
using Microsoft.Practices.Unity;

namespace UnityForTheWebLib
{
    public static class HttpApplicationStateExtensions
    {
        private const string GlobalContainerKey = "Your global Unity container";

        public static IUnityContainer GetContainer(this HttpApplicationState application)
        {
            application.Lock();
            try
            {
                IUnityContainer container = application[GlobalContainerKey] as IUnityContainer;
                if(container == null)
                {
                    container = new UnityContainer();
                    application[GlobalContainerKey] = container;
                }
                return container;
            }
            finally
            {
                application.UnLock();
            }
        }
    }
}

Basically, we have lazy initialization of the container and a mechanism to stuff it into the application state.  And then the initial HttpModule that only does injection on a Page:

using System;
using System.Collections.Generic;
using System.Web;
using System.Web.UI;
using Microsoft.Practices.Unity;

namespace UnityForTheWebLib
{
    public class UnityHttpModule : IHttpModule
    {
        #region IHttpModule Members

        ///<summary>
        ///Initializes a module and prepares it to handle requests.
        ///</summary>
        ///
        ///<param name="context">An <see cref="T:System.Web.HttpApplication"></see> that provides access to the methods, properties, and events common to all application objects within an ASP.NET application </param>
        public void Init(HttpApplication context)
        {
            context.PreRequestHandlerExecute += OnPreRequestHandlerExecute;
        }

        ///<summary>
        ///Disposes of the resources (other than memory) used by the module that implements <see cref="T:System.Web.IHttpModule"></see>.
        ///</summary>
        ///
        public void Dispose()
        {
        }

        #endregion

        private void OnPreRequestHandlerExecute(object sender, EventArgs e)
        {
            IHttpHandler handler = HttpContext.Current.Handler;
            HttpContext.Current.Application.GetContainer().BuildUp(handler.GetType(), handler);
        }
    }
}

This is a very simple module that calls BuildUp on the page. 

At this point we added another test, and implemented it.  After a few iterations of this we ended up with tests for injection into a User Control and a Master Page, an interface that needed to be configured on the container.  The final implementation of the Http Module looks like this

using System;
using System.Collections.Generic;
using System.Web;
using System.Web.UI;
using Microsoft.Practices.Unity;

namespace UnityForTheWebLib
{
    public class UnityHttpModule :
IHttpModule
   
{
        #region IHttpModule Members

       
///<summary>
        ///
Initializes a module and prepares it to handle requests.
       
///</summary>
        ///
        ///<param name="context">
An <see cref="T:System.Web.HttpApplication"></see> that provides access to the methods, properties, and events common to all application objects within an ASP.NET application
</param>
       
public void Init(HttpApplication context)
        {
            context.PreRequestHandlerExecute += OnPreRequestHandlerExecute;
        }

       
///<summary>
        ///
Disposes of the resources (other than memory) used by the module that implements <see cref="T:System.Web.IHttpModule"></see>
.
       
///</summary>
        ///
       
public void Dispose()
        {
        }

       
#endregion

        private void
OnPreRequestHandlerExecute(object sender, EventArgs e)
        {
            IHttpHandler handler = HttpContext.Current.Handler;
            HttpContext.Current.Application.GetContainer().BuildUp(handler.GetType(), handler);

           
// User Controls are ready to be built up after the page initialization is complete
           
Page page = HttpContext.Current.Handler as Page;
            if (page != null)
            {
                page.InitComplete += OnPageInitComplete;
            }
        }

       
// Get the controls in the page's control tree excluding the page itself
       
private IEnumerable<Control> GetControlTree(Control root)
        {
            foreach (Control child in root.Controls)
            {
                yield return child;
                foreach (Control c in GetControlTree(child))
                {
                    yield return c;
                }
            }
        }

       
// Build up each control in the page's control tree
       
private void OnPageInitComplete(object sender, EventArgs e)
        {
            Page page = (Page) sender;
            IUnityContainer container = HttpContext.Current.Application.GetContainer();
            foreach (Control c in GetControlTree(page))
            {
                container.BuildUp(c.GetType(), c);
            }
        }
    }
}

Configuration of the container can happen in the Global Application_Start handler like this:

using System;
using Microsoft.Practices.Unity;

namespace UnityForTheWebTestSite
{
    public class Global : System.Web.HttpApplication
    {

        protected void Application_Start(object sender, EventArgs e)
        {
            IUnityContainer c = Application.GetContainer();
            c.RegisterType<IControlData, ControlData1>();
        }
    }
}

So, from the initial requirements we have this:

  • Create a DI container for the application Lazy initialization
  • Create a way to get to the container ( we choose an extension method on the Application class) Extension Method
  • Allow a way to configure the container Application Start
  • Allow DI to work for pages  Add the HttpModule and Attributes
  • Allow DI to work for user controls Add the HttpModule and Attributes
  • Allow DI to work for master pages Add the HttpModule and Attributes
  • Allow DI to work for ASMX web services
  • Allow the above functionality in a simple and self contained way This is all in a single module
We met the last requirement (simple and self contained) since all we did to the web application was add a single line to the web config.  That met the requirement.

The last area is one we met, but we are not happy with the solution.  Basically, we need to do a bit more research and see if there is a way to get into the pipeline for an ASMX request early enough to do injection and not screw things up for the normal use case or the Ajax extensions.  Until we get this figured out right, the solution is to have your Web Service constructor ask the container to do injection.  This is an ugly hack and looks something like this:

using System.ComponentModel;
using System.Web;
using System.Web.Services;
using Microsoft.Practices.Unity;

namespace UnityForTheWebTestSite
{
    [WebService(Namespace = "http://tempuri.org/")]
    [WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
    [ToolboxItem(false)]
    // To allow this Web Service to be called from script, using ASP.NET AJAX, uncomment the following line. 
    // [System.Web.Script.Services.ScriptService]
    public class MyWebService : System.Web.Services.WebService
    {
        public MyWebService()
        {
            HttpContext.Current.Application.GetContainer().BuildUp(this);
        }

        [Dependency]
        public IControlData Data
        {
            get;
            set;
        }

        [WebMethod]
        public string HelloWorld()
        {
            return "Hello World " + Data.GetText();
        }
    }
}

To add the ability to have a container at the Session level and the request level should be as simple as following the pattern for the extension method and the http handler above. (I will leave it as an exercise for the reader.) You could use the same container for everything, or have the Session container a child of the application container, and the request container a child of the session container.  When and if we do a real implementation (as opposed to a proof of concept) we will figure out the best approach for most cases.  When and if this happens, I will update my CWAB with Unity solution and dramatically simplify it. :-)

Acceptance Testing Guide Update

The team has been writing, editing, re-writing, and working hard on putting together a guide on Acceptance Testing.  We have made quite a bit of progress, decided on an organization scheme, the basic format of how we want to write each chapter, and have re-worked a lot of content to fit this model.  We recently posted two things on the Acceptance Testing Guidance CodePlex site:

So, please answer our survey.  It only has ONE question.

Also, send us feedback on the draft sections of the guide we posted by starting up some discussions in the Acceptance Testing Guide Discussions group.

Converting the Composite Web Application Block to Unity - Using the UnityCompositionContainer

This is the sixth post in a series. The other post include:

If you want background, go read the earlier posts.

Based upon feedback, I am making the source code available at CWAB and Unity.

For those who have been following along, you all know I am making this up as I go. So, I am asking that you be patient with me as we figure this out together. This article (in particular) may have a few false starts, and "ooops" moments.  We are replacing something that was not meant to be pluggable, and all of the refactoring work that has been done up to this point may not be enough.

Reminder:  This is a proof of concept.  The version of CWAB I am creating here is not a supported product or guidance from patterns & practices.  If you really want Unity support in WCSF, please go to the Issue Tracker on the WCSF Community Site and vote for the work item to get Unity support for WCSF.

At the end of the last post I planned on trying to actually use the UnityCompositionContainer, and then nuke the old CompositionContainer.

Let's get started by replacing any calls that creates a CompositionContainer with code that creates a UnityCompositionContainer.  There is ONE spot, in WebClientApplication.  Simple. Change, recompile, re-run unit tests, and we are green.

If it really was that simple, we should be able to remove the CompositionContainer class (and its test fixture) from the solution, and not have any challenges.  Let's try that.

We fail to compile.  Our TestableRootCompositionContainer is part of the problem. MockContainer in ManagedObjectCollectionFixture is the rest of it.

If we derive TestableRootCompositionContainer from UnityContainer, and remove everything from the class (as a temporary measure), we go from two to 27 build errors. 

<timewarp duration="an or two"/>

Not good.  But not too bad, considering what comes next.  After fixing these build errors, I got on a roll, and did the following:

  • Removed references to the old ObjectBuilder.dll in both unit test and system projects
  • Removed the BuilderStrategies folder in both unit test and system projects
  • Removed the Collections folder in both unit test and system projects
  • Removed the ObjectBuilder folder in both unit test and system projects
  • Removed the ProviderDependencyAttribute and its fixture
  • Removed StateDependencyAttribute and its fixture
  • Removed OptionalDependencyAttribute and its fixture
  • Removed ServiceDependencyAttribute and its fixture
  • Removed all references to the old ObjectBuilder namespace
  • Replaced any [CreateNew] attributes with the Unity [Dependency] attribute
  • Hacked on WebClientApplication
  • Removed the Services collection.  Replaced calls to container.Services.Add with container.RegisterType.  If needed added a call to container.Resolve, when the Services.Add call was supposed to return an object.

Ok, things are compiling again.  Finally.  But there are a few failing unit tests, about 20 or so...  Let's fix those.

<type... type.... swear.... type />

Getting those test to pass was fairly simple.  All of them required a little bit of container setup that was different than before.  This was not a big deal.

There is one major change I did make in the process, and a related renaming.  First, the renaming, Page became InjectablePage; MasterPage became InjectableMasterPage, and guess what UserControl became? Excactly, InjectableUserControl.  These are better descriptions and will remove the confusion I have dealt with on the forums where people use the wrong Page base class.  The other change is that, previously CompositionContainer had two Builders: one for things like services that stayed around, and another for Pages and transient items like presenters.  We no longer need two builders, and can get containers and lifetime managers to handle the differences.  The approach I took for simplicity is to have each page create a container that is a child of the correct Module container, use this for doing injection on the page, and then nuking the container on Page.Dispose.  This is quick and dirty, and it works, but I may revisit it later.

Now, since Unity 1.1 just shipped, it is time to upgrade.  I replaced the binaries and...

Everything still passes.

I think that is enough for today.

As a quick check, I just looked at the solution statistics for the original version of CWAB and the current solution.  CWAB went from 26KLOC (pre-article one) to 14KLOC, both numbers including unit tests.  And I bet that there is more to be cut out and cleaned up.  Having a purpose built, re-usable component for DI helped a lot here.  For this edition, windiff will probably be the best bet for following all the types of changes I made.  This one took a while and impacted a lot of code.

Next, I am going to review unit tests, run code coverage, determine if there are gaps in test coverage after all the hacking.  After that, it will be porting one of the quickstarts over to the new version of CWAB.  After that, the RI, at which point I will be sure that the updated version works well enough to be a good proof of concept.

Acceptance Testing Guidance Survey

We have put together a survey to get a bit more input from the community about Acceptance Testing.  If you are at all involved in software development, deployment, or operations acceptance testing proabably impacts you in some way, shape, or form, so you may want to add your insight to what we are working on.

You can find it here: Acceptance Testing Survey

Thanks for the feedback and input.

Enterprise Library 4.0 and Unity 1.1 Shipped

Grigori has announced that Enterprise Library 4.0 has shipped.

You can get EntLib 4 here.  I have been watching this team work hard for the last few months, had a number of conversations with Chris about it, looked at a few problems (note: I did not say I helped solve these problems, I just looked, asked stupid questions, and that allowed Chris to figure them out).  This should be a solid release with some great features, bug fixes, and performance improvements.

Unity 1.1 has also shipped.  EntLib 4.0 is built on top of Unity, and takes advantage of it.  I have said it before, Unity Rocks! 

Now, I need to upgrade to Unity 1.1 for my articles on re-writing the Composite Web Application Block to use Unity.

Posted by mpuleio | 0 Comments

Converting the Composite Web Application Block to Unity - Actually Adding Unity

This is the fifth post in a series. The other post include:

If you want background, go read the earlier posts.

Based upon feedback, I am making the source code available at CWAB and Unity.

First off, I have moved this little side project to source control, so I can avoid the re-work I had to do before I could write this part of the series.

Note to self :

NEVER work without a safety net.  That means both unit tests and source control.

Ok.  Now that that is out of the way....

Let's go add Unity to CWAB, via EDD (formerly TDD).

How can we do this?  First, we need a test fixture.  So, I added CompositionContainerFixture to the CompositeWeb.Tests project as an empty test fixture.  And then I added the following very simple test as a starting point:

[TestMethod]
public void UnityCompositionContainerIsICompositionContainer()
{
    UnityCompositionContainer container = new UnityCompositionContainer();
    Assert.IsInstanceOfType(container, typeof(ICompositionContainer));
}

This will allow me to write enough code to create the UnityCompositionContainer class and ensure that it implements the right interface.

Making the test compile forces me to create a new UnityCompositionContainer class (I added it to the fixture as a nested class for the moment), and the test fails.  No problem.  I add the interface, implement it with methods that throw, and..... We are green again. 

Next step, I copied the unit test RootContainerParentIsNull over, changed its name to NewUnityContainerParentIsNull, updated it to create a new UnityCompositionContainer, and compiled and ran the test.  It passed, which is not idea;l, but I will leave it an move on, knowing it will be important later.  For the next test, I copied ChildContainerHasParent changed its name to NewUnityContainerParentIsNull, updated it to create a new UnityCompositionContainer, and compiled and ran the test... Red. Just like we expected.  To make this work, I could do a bit of throw away work, or I could add Unity.  I feel like I can skip the simplest thing possible, because I know where I want to go. 

However, first, I'm doing a check-in.  I'll comment out the failing test, and sync up.  Just a sec.

<click click>

Ok, now To add Unity.  I grabbed the binaries from MSDN, dropped them in my tree in the Lib folder and we are good to go.  I added references in the CWAB projecct to Unity.DLL and ObjectBuilder2.DLL.  This means we have two completely separate DI systems as part of out code, which is awful.  However, it won't last too long.

Now, we can make that test pass.  I added an IUnityContainer field to UnityCompositionContainer.  I then implemented a constructor to initialize it.  Then we needed to implement CreateChildContainer.  For this, the simplest thing was to create a new constructor for UnityCompositionContainer which takes a parent container as the only parameter.  After a little wire-up we end up with passing tests and this code:

private UnityCompositionContainer(UnityCompositionContainer parentContainer)
{
    Parent = parentContainer;
    wrappedContainer = parentContainer.wrappedContainer.CreateChildContainer();
}
public ICompositionContainer CreateChildContainer()
{
    UnityCompositionContainer child = new UnityCompositionContainer(this);
    return child;
}

Fairly simple.  I will continue moving unit tests over, adapting them, and making them pass.  If there are any interesting deviations from normal, or new tests added, I'll let you know.

<timewarp duration="a short while" />

That was actually fairly simple.  I copied the tests one at a time, replaced the container used with the UnityCompositionContainer, compiled, ran the tests, watched them fail due to NotImplementedExceptions, and fixed them.  Here's the test fixture:

[TestClass]
public class UnityCompositionContainerFixture
{
    [TestMethod]
    public void UnityCompositionContainerIsICompositionContainer()
    {
        UnityCompositionContainer container = new UnityCompositionContainer();
        Assert.IsInstanceOfType(container, typeof (ICompositionContainer));
    }

    [TestMethod]
    public void NewUnityContainerParentIsNull()
    {
        ICompositionContainer container = new UnityCompositionContainer();
        Assert.IsNull(container.Parent);
    }

    [TestMethod]
    public void ChildContainerHasParent()
    {
        ICompositionContainer parent = new UnityCompositionContainer();

        ICompositionContainer child = parent.CreateChildContainer();

        Assert.AreSame(parent, child.Parent);
    }

    [TestMethod]
    public void CanRegisterTypeMappingOnRootContainer()
    {
        UnityCompositionContainer root = new UnityCompositionContainer();

        root.RegisterType<IFoo, Foo>();

        IFoo resolvedIFoo = root.Resolve<IFoo>();

        Assert.AreEqual(typeof (Foo), resolvedIFoo.GetType());
    }

    [TestMethod]
    public void CanRegisterTypeMappingViaTypeObjects()
    {
        UnityCompositionContainer root = new UnityCompositionContainer();
        root.RegisterType(typeof (IFoo), typeof (Foo));

        IFoo resolvedIFoo = root.Resolve<IFoo>();

        Assert.AreEqual(typeof (Foo), resolvedIFoo.GetType());
    }

    [TestMethod]
    public void RequestingTypeMappingForUnmappedTypeReturnsRequestedType()
    {
        UnityCompositionContainer root = new UnityCompositionContainer();

        Foo resolvedFoo = root.Resolve<Foo>();

        Assert.AreEqual(typeof (Foo), resolvedFoo.GetType());
    }

    [TestMethod]
    [ExpectedException(typeof (ArgumentException))]
    public void TypeMappingsMustBeTypeCompatible()
    {
        UnityCompositionContainer root = new UnityCompositionContainer();
        root.RegisterType(typeof (IBar), typeof (Foo));
    }

    [TestMethod]
    public void CanRegisterMultipleTypeMappings()
    {
        UnityCompositionContainer root = new UnityCompositionContainer();

        root.RegisterType<IFoo, Foo>();
        root.RegisterType<IBar, Bar>();
        IBar b = root.Resolve<IBar>();
        IFoo f = root.Resolve<IFoo>();

        Assert.AreEqual(typeof (Bar), b.GetType());
        Assert.AreEqual(typeof (Foo), f.GetType());
    }

    [TestMethod]
    public void RequestingTypeMappingOnChildReadsFromParent()
    {
        UnityCompositionContainer parent = new UnityCompositionContainer();
        ICompositionContainer child = (ICompositionContainer) parent.CreateChildContainer();

        parent.RegisterType<IFoo, Foo>();

        Assert.AreEqual(typeof (Foo), child.Resolve<IFoo>().GetType());
    }

    [TestMethod]
    public void ChildContainersCanOverrideParentTypeMapping()
    {
        UnityCompositionContainer parent = new UnityCompositionContainer();
        ICompositionContainer child = (UnityCompositionContainer) parent.CreateChildContainer();

        parent.RegisterType<IFoo, Foo>();
        child.RegisterType<IFoo, Foo2>();

        Assert.AreEqual(typeof (Foo), parent.Resolve<IFoo>().GetType());
        Assert.AreEqual(typeof (Foo2), child.Resolve<IFoo>().GetType());
    }

    [TestMethod]
    public void CanCreateChildContainer()
    {
        ICompositionContainer container = new UnityCompositionContainer();

        ICompositionContainer child = container.CreateChildContainer();
        Assert.IsNotNull(child);
        Assert.AreNotSame(container, child);
    }

    [TestMethod]
    public void CanRegisterInstance()
    {
        UnityCompositionContainer root = new UnityCompositionContainer();
        root.RegisterInstance(typeof (string), "foo", "bar");
        string returned = (string) root.Resolve(typeof (string), "foo");
        Assert.AreEqual("bar", returned);
    }


    [TestMethod]
    public void CanRegisterInstanceViaGenericWithoutName()
    {
        ICompositionContainer root = new UnityCompositionContainer();
        Foo f1 = new Foo();
        root.RegisterInstance<Foo>(f1);
        Foo returnedFoo = (Foo) root.Resolve(typeof (Foo));
        Assert.AreEqual(f1, returnedFoo);
    }

    [TestMethod]
    public void CanRegisterInstanceViaGenericWithName()
    {
        ICompositionContainer root = new UnityCompositionContainer();
        Foo f1 = new Foo();
        root.RegisterInstance<Foo>("asdf", f1);
        Foo returnedFoo = (Foo) root.Resolve(typeof (Foo), "asdf");
        Assert.AreEqual(f1, returnedFoo);
    }


    [TestMethod]
    public void CanResolveViaGenericWithoutName()
    {
        ICompositionContainer root = new UnityCompositionContainer();
        Foo f1 = new Foo();
        root.RegisterInstance<Foo>(f1);
        Foo returnedFoo = root.Resolve<Foo>();
        Assert.AreEqual(f1, returnedFoo);
    }

    [TestMethod]
    public void CanResolveInstanceViaGenericWithName()
    {
        ICompositionContainer root = new UnityCompositionContainer();
        Foo f1 = new Foo();
        root.RegisterInstance<Foo>("asdf", f1);
        Foo returnedFoo = root.Resolve<Foo>("asdf");
        Assert.AreEqual(f1, returnedFoo);
    }

    [TestMethod]
    public void UnityCompositionContainerImplementsIDisposable()
    {
        UnityCompositionContainer disposableContainer = new UnityCompositionContainer();
        Assert.IsNotNull(disposableContainer as IDisposable);
    }

    // This test is commented out intentionally. The purpose of this test is to show 
    // that if you use the generic version of the RegisterTypeMapping method, if the
    // types aren't compatible it'll fail at compile time. 
    // 
    // This is exactly what happens. However that also means this file won't compile.
    // The test is left in as comments, if you wish to verify this then remove the comments,
    // watch the compile file, and then comment it out again.

    //[TestMethod]
    //public void GenericTypeMappingRegistrationEnforcesCompileTimeCompatibility()
    //{
    //    UnityCompositionContainer root = new UnityCompositionContainer();
    //    root.RegisterType<IBar, Foo>();
    //}
}

Notice, there are no tests for the Services collection.  This is intentional.  We will see if we can avoid implementing the methods at all.

And here is the code to make those tests pass:

public class UnityCompositionContainer : ICompositionContainer, IDisposable
{
    private ICompositionContainer parent = null;
    private IUnityContainer wrappedContainer;

    public UnityCompositionContainer()
    {
        wrappedContainer = new UnityContainer();
    }

    private UnityCompositionContainer(UnityCompositionContainer parentContainer)
    {
        Parent = parentContainer;
        wrappedContainer = parentContainer.wrappedContainer.CreateChildContainer();
    }

    public ICompositionContainer Parent
    {
        get { return parent; }
        set { parent = value; }
    }

    public IServiceCollection Services
    {
        get { throw new NotImplementedException(); // return services; 
        }
    }

    public void RegisterInstance(Type t, object instance)
    {
        wrappedContainer.RegisterInstance(t, instance);
    }

    public void RegisterInstance(Type t, string name, object instance)
    {
        wrappedContainer.RegisterInstance(t, name, instance);
    }

    public void RegisterInstance<TInterface>(TInterface instance)
    {
        wrappedContainer.RegisterInstance<TInterface>(instance);
    }

    public void RegisterInstance<TInterface>(string name, TInterface instance)
    {
        wrappedContainer.RegisterInstance<TInterface>(name, instance);
    }

    public void RegisterType<TRequested, TReturned>() where TReturned : TRequested
    {
        wrappedContainer.RegisterType<TRequested, TReturned>();
    }

    public void RegisterType(Type requested, Type returned)
    {
        wrappedContainer.RegisterType(requested, returned);
    }

    public object Resolve(Type typeOfItem)
    {
        return wrappedContainer.Resolve(typeOfItem);
    }

    public object Resolve(Type typeOfItem, string name)
    {
        return wrappedContainer.Resolve(typeOfItem, name);
    }

    public T Resolve<T>()
    {
        return wrappedContainer.Resolve<T>();
    }

    public T Resolve<T>(string name)
    {
        return wrappedContainer.Resolve<T>(name);
    }

    public object BuildItem(IBuilder<WCSFBuilderStage> builder, object item)
    {
        throw new NotImplementedException();
    }

    public ICompositionContainer CreateChildContainer()
    {
        UnityCompositionContainer child = new UnityCompositionContainer(this);
        return child;
    }

    public void Dispose()
    {
        wrappedContainer.Dispose();
        wrappedContainer = null;
    }
}

We are now in a green state, time to check in.

Abusing Source Control

Agile teams usually check in very often.  Some teams check in every time they hit green.  I think that is a bit of overkill, unless you have a source control system with NO overhead.  I check in when I complete a feature or a story, and usually at a few good, green stopping points in the process, like I have been doing.  This was a good stopping point, and my next task is a bit risky, so this is a perfect time to check in.

This is a long enough post, even though I didn't do all that much, that I will call it quits for today.  Next post, actually use the UnityCompositionContainer, and then nuke the old CompositionContainer.

ScrumBut

I worked on my first XP project with John Boal.  He recently did a post on ScrumBut.  I have mentioned ScrumBut and Scrummerfall before, but this is a good, quick read with a few good tips.  A lot of the concepts carry over to XP as well.

 

I'll add something though: Make sure your stories have acceptance criteria defined before you start working on them. This way you know when you are done. :)

 

Enjoy.

Posted by mpuleio | 0 Comments

We really do listen to community feedback

The other day, we shipped the Smart Client Software Factory April 2008 Release. Before we shipped, I asked the team to audit all the open work items in the queue on the SCSF community site's Issue Tracker and determine what we had fixed.  We had used the items in the Issue Tracker before and during the project, to help guide some of the bug fixes and features.  However, the audit allowed us to do some clean up and ensure we fixed a few things.  Today, I used the results of that audit, and closed a few work items. 

<Sidebar>

I did cheat a bit: I used the Visual Studio Team System integration with CodePlex so I could open up the list of all open work items in an Excel spreadsheet and publish changes back to the live Codeplex site.  This made bulk editing a whole lot simpler, and saved me a lot of time. 

</Sidebar>

Here are the results of the audit and work item closures:

  • Out of 89 open work items/ issues, we closed 45 today.  A number of these had been fixed in the May 2007 release and never closed, a number were fixed in this release, and some were related to different weekly drops.
  • Out of the top 25 items (by community votes), we closed 13.
  • Looked at another way, we closed 1/2 of the open issues, and 1/2 of the top issues. Not bad.

So, keep up the discussion in our communities.  We reply on the discussion boards, we actually do look at the open work items on occasion, and we do listen to the community.

Smart Client Software Factory – April 2008 Release is available on MSDN

The April 2008 release of the Smart Client Software Factory is now available at http://msdn2.microsoft.com/en-us/library/aa480482.aspx

This is a port of the last release (May 2007, if I recall correctly) to VS2008.  No new features were added.  A few bugs were fixed, and a number of work items from CodePlex were closed.

This release supports Enterprise Library 3.1.  It does not support Enterprise Library 4.0.  If you want EntLib 4.0 (once it is released) you have the source code, and should be able to get it to work, if you really need to.  I would not recommend it, as you will end up with two containers (Unity and the CAB container), which means code bloat and challenges deciding where objects should go.

 

Converting the Composite Web Application Block to Unity - Ummmm...Oooops.

This is the forth post in a series. The other post include

If you want background, go read the earlier posts.

Based upon feedback, I am making the source code available at CWAB and Unity.

In the last installment I wanted to remove the following from the ICompositionContainer:

  • static methods
  • Builder
  • Locator
  • Containers
  • Services

We completed the first four. In this installment, we will remove the Services collection, replacing it with using RegisterInstance and Resolve. After that, we will compare our ICompositionContainer to IUnityContainer, see what else we need to do, and may even pull in Unity.

Adding a few new methods

Before we do this, I want to add a generic overload to Resolve and one to RegisterInstance.  I like the way the generic calls on Unity look, compared to all the typeof() and casting we have done so far. 

I added the following tests, one at a time, and made them pass:

[TestMethod]
public void CanRegisterInstanceViaGenericWithoutName()
{
    ICompositionContainer root = new TestableRootCompositionContainer();
    Foo f1 = new Foo();
    root.RegisterInstance<Foo>(f1);
    Foo returnedFoo = (Foo)root.Resolve(typeof(Foo));
    Assert.AreEqual(f1, returnedFoo);
}

[TestMethod]
public void CanRegisterInstanceViaGenericWithName()
{
    ICompositionContainer root = new TestableRootCompositionContainer();
    Foo f1 = new Foo();
    root.RegisterInstance<Foo>("asdf", f1);
    Foo returnedFoo = (Foo)root.Resolve(typeof(Foo), "asdf");
    Assert.AreEqual(f1, returnedFoo);
}


[TestMethod]
public void CanResolveViaGenericWithoutName()
{
    ICompositionContainer root = new TestableRootCompositionContainer();
    Foo f1 = new Foo();
    root.RegisterInstance<Foo>(f1);
    Foo returnedFoo = root.Resolve<Foo>();
    Assert.AreEqual(f1, returnedFoo);
}

[TestMethod]
public void CanResolveInstanceViaGenericWithName()
{
    ICompositionContainer root = new TestableRootCompositionContainer();
    Foo f1 = new Foo();
    root.RegisterInstance<Foo>("asdf", f1);
    Foo returnedFoo = root.Resolve<Foo>("asdf");
    Assert.AreEqual(f1, returnedFoo);
}

 

In making them pass, I added the following to the ICompositionContainer interface:

T Resolve<T>();
T Resolve<T>(string name);
void RegisterInstance<TInterface>(TInterface instance);
void RegisterInstance<TInterface>(string name, TInterface instance);

This will help a bit with the look, feel, and style of the code, now for the real work.

Removing the Services Collection

Why do we want to remove the Services collection?  Since Unity handles this sort of functionality, we can offload it entirely to Unity.  This will cut a bit of code out of our implementation.

Let's do this the simple way, (I like to call it hack and slash development) and just remove the Services collection from the ICompositionContainer interface.  This will result in a number of build errors (twenty or so, in fact).  However, we can fix each of them easily.  Any call to add a service becomes a RegisterInstance call, and any call to get a service becomes a Resolve call.  So, we will hack each problem until we are in a green state again.  The other option, for the less daring, is to search for all uses of Services, change them one at a time, and make sure we are green at each step.  Today, I am feeling brave (read: reckless, or overly caffeinated), so I took the other approach.  If I were pairing with someone, they would probably stop me. :-)

Once CWAB compiles, we still need to get the unit test library to compile.  <click click click> <swear> <click click click>.  The biggest challenge here is that Services.AddNew<T, IT> and RegisterType<IT, T> have the generic parameters in reversed order.  Aaargh.

Everything compiles, but I have a problem: 34 unit tests are failing.  This is not optimal.  Now, why are they failing?  After looking at the first few, it looks like I removed Services from the interface, and forgot to remove it from the CompositionContainer.  The result is that some tests are still using the ServicesCollection.  Oooops.

After removing Services from CompostionContainer, and getting everything to compile again, the test results are.....

Ouch!  40 failing unit tests.  That is not good.

However, after some investigation, I can remove a couple of classes from our solution, as they are no longer necessary, and are just causing problems.

ServiceDependencyParameterResolver
ProviderDependencyParameterResolver
ProviderDependencyAttribute
ServiceDependencyAttribute

After removing them, there is a bit of code cleanup required, to remove references.  All of the ServiceDependencyAttributes I replaced with ObjectBuilder DependencyAttributes.  The ProviderAttributes, I commented out for the moment.

Wow. Progress. we are down to 37 failing tests. After looking at a few of them, where instances were not the same, I changed the SingletonPolicy in Resolve, and we are down to 24 failing tests.

Oh, gotta take a break.

<TimeWarp>Several Days Fly By</TimeWarp>

I got interrupted from getting this working the other day.  Now, I am starting with broken tests.  I hate that.  I guess I was a bit too reckless.  Well, I have a few options:

  1. I can continue and see this through
  2. I can timebox to a hour, and then roll back, and try again by taking smaller steps
  3. I can give up now and try again from the last known good state.

I am going to opt for number 1.5: timebox to two hours, and depending on where I am, make a decision.

<timewarp duration="1 hour" />

@#$%^%$#@#$!!!

<timewarp duration="a few days" reason="I needed to think about it" />

I have determined that I got a bit overzealous.  For the moment, the Services collection is necessary, and we can remove it once we have Unity in place to provide the necessary functionality.  It will stay as part of the interface, and will continue to provide functionality until we no longer need it.  However, it will eventually go away.  How did I arrive at this conclusion?  Well, I could not get the failing unit tests to pass in a reasonable amount of time.  Moving the functionality requires a lot more code than is really practical for throw-away code.  Oooops.  Everyone makes mistakes. 

As a result, I need to roll back a lot of changes.  Unfortunately, I did not back up everything (or do a check in) before starting down the path of removing the services collection.  Net result: I need to roll back everything, and then re-do the first half of this article. Double @#%$@%!

I'll revert and then rework the code up to the section Removing the Services Collection.  I'll get the code posted (with the other source code) before I start the next installment.

However, I wanted to post this article sooner rather than later, so folks don't think I have dropped the series.  Enjoy.

Smart Client Software Factory April 2008 Release Candidate Available

Friday, I posted we had a solid Beta.  Today, I am letting you know that SCSF now has a Release Candidate (RC).  The bug that appeared Friday is, we think, fixed.  We actually published the RC before we completed any internal testing, so the customer who reported the issue would have a chance to verify the fix works on their system ASAP.  Don't worry, we will do a solid test pass before determining if this RC will become the official release. (The fact that we are confident in our build system and the automated tests there helps with this sort of turnaround. :-) )

Please try out the Smart Client Software Factory April 2008 Release Candidate, and report any issues on the SCSF CodePlex community site.

More Posts Next page »
 
Page view tracker