An Object Constructor Class for Handling Dependency Injection

When designing code that can be unit tested, a primary concern is breaking any external dependencies that your class may have. One option is to use constructor or property injection to allow the objects to be replaced by stubs or mocks in the unit tests. However, this could become cumbersome, especially if there are a number of dependencies.

A simple alternative is to create a class that handles the creation of objects. For production code, the class needs to simply return an object of the type requested. We’ll create two methods, one that uses the default constructor and one that allows the caller to provide a constructor.

    public static class ObjectConstructor
    {
        public static T GetObject<T>() where T : new()
        {
            return GetObject(() => new T());
        }

        public static T GetObject<T>(Func<T> constructor)
        {
            return constructor();
        }
    }

Now, we need to add a way to replace the object created with a stub or a mock for unit tests. We can do this by maintaining a list of objects. When an object is requested, it will first look in that list. Otherwise, it will build the object using the constructor.

    public static class ObjectConstructor
    {
        static SortedList<string, object> _objects = new SortedList<string, object>();

        public static T GetObject<T>() where T : new()
        {
            return GetObject(() => new T());
        }

        public static T GetObject<T>(Func<T> constructor)
        {
            var typeName = typeof(T).FullName ?? string.Empty;
            if (!_objects.ContainsKey(typeName))
                return constructor();
            return (T)_objects[typeName];
        }

        public static void AddObject<T>(T obj)
        {
           var typeName = typeof(T).FullName ?? string.Empty;
           _objects.Add(typeName, obj);
        }

    }

Finally, we’ll also add some additional methods for removing objects. We also want to make sure that our class is thread safe, so we to also need add some locks to the code.

    public static class ObjectConstructor
    {
        static SortedList<string, object> _objects = new SortedList<string, object>();
        static Object lockObj = new object();

        public static T GetObject<T>() where T : new()
        {
            return GetObject(() => new T());
        }

        public static T GetObject<T>(Func<T> constructor)
        {
            lock (lockObj)
            {
                var typeName = typeof(T).FullName ?? string.Empty;
                if (!_objects.ContainsKey(typeName))
                    return constructor();
                return (T)_objects[typeName];
            }
        }

        public static void AddObject<T>(T obj)
        {
            lock (lockObj)
            {
                RemoveObject<T>();
                var typeName = typeof(T).FullName ?? string.Empty;
                _objects.Add(typeName, obj);
            }
        }

        public static void RemoveObject<T>()
        {
            lock (lockObj)
            {
                var typeName = typeof(T).FullName ?? string.Empty;
                if (_objects.ContainsKey(typeName))
                    _objects.Remove(typeName);
            }
        }

        public static void ClearObjects()
        {
            lock (lockObj)
            {
                _objects = new SortedList<string, object>();
            }
        }
    }

To use the class, create your objects using a call to the GetObject method. Below are examples of how to use both the default constructor and how to provide the constructor as input.

var accountRepository1 = ObjectConstructor.GetObject<AccountRepository>();
var accountRepository2 = ObjectConstructor.GetObject(() => new AccountRepository(parm));

In the setup for your unit test, add your mocked object to the ObjectConstructor. Then, the subsequent call to GetObject will return the mocked object.

ObjectConstructor.AddObject(mockedAccountRepository);

Since only the test code will add objects, all your production objects will be created using their constructors. So, you now have a reusable class for creating your objects and allowing an easy way to handle dependency injection.

Using a SharePoint 2010 Supplemental Config File to Add App Settings

SharePoint 2010 allows you to create a supplemental .config file that can be merged with SharePoint’s web.config when the feature is deployed. MSDN provides instructions on doing this: http://msdn.microsoft.com/en-us/library/ms439965.aspx

By following their instructions, you can easily adding sections to the web.config. What is not obvious from their instructions, though, is how to add individual keys within a section, such as in AppSettings.

Adding the key is not complicated. You can do this by adding XML such as the following:

<add path="configuration/appSettings">
  <add key="testUrl" value="http://ipaddress"  />
</add>

However, you should also add a corresponding XML to remove the setting.  This will prevent duplicate entries if the config file is merged multiple times.

This turns out to be straight forward as well, once you realize that it expects an xpath expression as the path. Here’s how you would remove the key from AppSettings that we just added:

<remove path="configuration/appSettings/add[@key='testUrl']"/>

Creating a SharePoint 2010 Page Layout with Code Behind

If you are working with a Publishing Site and need to include complex logic in one or more of your pages, you may want to build a page layout that includes a code behind file.

To get started, setup your page layout in Visual Studio. Becky Bertram’s blog, Creating a Page Layout in SharePoint 2010 using Visual Studio 2010, walks you through the setup.

Once you have your page layout setup and working, adding the code behind file is easy. Simply add a new text file to your module with the name of your code behind file. Visual Studio will automatically add it under your existing page.

image

Your code behind class should inherit from the PublishingLayoutPage, so you will need to add a reference to Microsoft.SharePoint.Publishing. Then, go ahead and add your code as you normally would.

using System;
using System.Web.UI.WebControls;

namespace PageLayoutDemo
{
    public class DemoPageLayout : Microsoft.SharePoint.Publishing.PublishingLayoutPage
    {
        protected Label lblResult;

        protected void Page_Load(object sender, EventArgs e)
        {
                lblResult.Text = "Page Load Called";
        }
    }
}

In order to make your code behind accessible to your ASPX page, you’ll want to make a few changes.

  • Add <%@ Assembly Name=”$SharePoint.Project.AssemblyFullName$” %>
  • Change the Inherits Attribute in the Page Directive to the name of your class
<%@ Assembly Name="$SharePoint.Project.AssemblyFullName$" %>
<%@ Page language="C#"  Inherits="PageLayoutDemo.DemoPageLayout"  %>
<%@ Register Tagprefix="SharePointWebControls" Namespace="Microsoft.SharePoint.WebControls" Assembly="Microsoft.SharePoint, Version=14.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c" %>
<%@ Register Tagprefix="WebPartPages" Namespace="Microsoft.SharePoint.WebPartPages" Assembly="Microsoft.SharePoint, Version=14.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c" %>
<%@ Register Tagprefix="PublishingWebControls" Namespace="Microsoft.SharePoint.Publishing.WebControls" Assembly="Microsoft.SharePoint.Publishing, Version=14.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c" %>
<%@ Register Tagprefix="PublishingNavigation" Namespace="Microsoft.SharePoint.Publishing.Navigation" Assembly="Microsoft.SharePoint.Publishing, Version=14.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c" %>

<asp:Content ContentPlaceholderID="PlaceHolderPageTitle" runat="server">
	<SharePointWebControls:FieldValue id="PageTitle" FieldName="Title" runat="server"/>
</asp:Content>

<asp:Content ContentPlaceholderID="PlaceHolderMain" runat="server">

   <PublishingWebControls:EditModePanel runat="server" id="EditModePanel1" PageDisplayMode="Display">
      <SharePointWebControls:FieldValue ID="FieldValue1" FieldName="PublishingPageContent" runat="server" />
   </PublishingWebControls:EditModePanel>

   <PublishingWebControls:EditModePanel runat="server" id="EditModePanel2" PageDisplayMode="Edit">
      <PublishingWebControls:RichHtmlField FieldName="PublishingPageContent" runat="server" id="RichHtmlField1"/>
   </PublishingWebControls:EditModePanel>

   <asp:Label id="lblResult" runat="server" ></asp:Label>             

</asp:Content>

Before you can use your new page layout, you’ll need to add a Safe Control Entry for the namespace. You can access the Safe Control Entries on the properties page of your Module.

image

From the Safe Control Entries page, click “Add”. The default properties are fine, so click “OK”.

image

Of course, you may want to keep your business and data access logic in separate assemblies. That is not an issue, but you’ll need to perform one last step to make sure that those assemblies get deployed as part of your SharePoint project. Open the package in your project and then click Advanced. There you can add additional assemblies.

image

Now, you’re ready to use your new page layout. Deploy your solution. Create a new page in your site and you’ll find your new page layout in the list.

image

Trick to set styles on a specific page in Web Forms & SharePoint

When working with ASP.NET sites, you typically have a master
page that contains all the common page elements on your site. Your header,
footer, sidebar, and navigation are nice and consistent. Everything is going
fine, and then someone decides that your company’s contact page should not have
the sidebar. How do you handle this?

Well, your first inclination might be to add some inline
styles on the about page to hide the sidebar for just that page. This works,
but you’re no longer following the best practice of having all CSS styles in an
external stylesheet. If your platform is heavily configuration driven, such as
in the case of SharePoint and other complex platforms, inline styles may not be easily added to a single page.

Thankfully, a simple modification to your master page can
make this easier.

In your master page, replace your body tag with the
following:

<body id="<%=System.IO.Path.GetFileNameWithoutExtension(Request.PhysicalPath).ToLower()%>_page" >

Once you do this, each page using the master will have an id
assigned to the body that is based off of the filename. For example, your
AboutUs.aspx will have the body tag:

<body id="aboutus_page">

Then you are free to write per-page exceptions in your
global CSS file like the following:

#aboutus_page .globalsidebar { display:none; }

Tada! Your sidebar is hidden on your about page, all others
are untouched, and all styles still reside in your stylesheet.

As this code creates an ID based off of the filename, it
assumes each page in your site is unique. This is not always the case as you
may have two pages with the same name but in different paths such as:
/Hardware/About.aspx and /Software/About.aspx. To handle this case, you’ll need
to get a little more creative. A few options would be:

  • Add a ContentPlaceholder inside the
    body tag’s ID value so that you can manually specify a value for each page.
  • Base the ID off of the entire URL path,
    which could create some very long IDs.