SharePoint Dependency Injection Approach

I just finished delivering a SharePoint workflow application in which I developed what could be called a start to framework that I would like to reuse in my next project.  The framework currently has many features such as:

  • An “Object-List Mapping” infrastructure complete with lazy initialization of objects and collections, converters, and caching
  • A list item event broker
  • Several handy web controls
  • Logging
  • State management
  • Plenty of Utility Helpers

Each major feature is defined with an interface, and there is a single context class scoped to an SPWeb that holds references to each feature provider.  For this last application, and I imagine I will do this for most applications going forward, I extended the context class to hold additional references to application-specific business logic helpers and data access interfaces.

In order to accomplish dependency injection of the feature providers, there is a context factory interface that is responsible for constructing and initializing contexts.   I implemented a static ”default” context factory that when called upon, it first looks in the SPWeb property bag to see if a predefined custom context factory type has been specified.  If it finds one, it constructs a new instance of the custom factory and returns the context from the custom factory’s CreateContext method.

    public static class SPAppContextFactory
    {
        public const string CustomSPAppContextFactoryKey = "custom_context_factory_key";
 
        public static void RegisterSPAppContextFactory<T>(this SPWeb web) where T : ISPAppContextFactory
        {
            web.AllProperties[CustomSPAppContextFactoryKey] = typeof(T).AssemblyQualifiedName;
            web.Update();
        }
 
        public static void UnregisterSPAppContextFactory(this SPWeb web)
        {
            if (web.Properties.ContainsKey(CustomSPAppContextFactoryKey))
            {
                web.AllProperties[CustomSPAppContextFactoryKey] = null;
                web.Update();
            }
        }
 
        public static SPAppContext CreateSPAppContext(this SPWeb web)
        {
            // First check Web Properties if an alternate factory is specified
            if (web.AllProperties.ContainsKey(CustomSPAppContextFactoryKey))
            {
                string customFactoryTypeName = web.AllProperties[CustomSPAppContextFactoryKey];
                Type customFactoryType = Type.GetType(customFactoryTypeName, true);
                ISPAppContextFactory customFactory = (ISPAppContextFactory)Activator.CreateInstance(customFactoryType);
                return customFactory.CreateContext(web);
            }
 
            // Create the Default Context
            return new SPAppContext(web);
        }

You can now register your applications custom context factory in the FeatureActivated method of a feature receiver. You’ll need to include the namespace of your static factory class in order to make the extension methods available, and then simply call the RegisterSPAppContextFactory extension method .

        public override void FeatureActivated(SPFeatureReceiverProperties properties)
        {
            var web = (SPWeb)properties.Feature.Parent;
            web.RegisterSPAppContextFactory<MyCustomContextFactoryClass>();
        }
 
        public override void FeatureDeactivating(SPFeatureReceiverProperties properties)
        {
            var web = (SPWeb)properties.Feature.Parent;
            web.UnregisterSPAppContextFactory();
        }

The context factory now serves as a single place where all dependencies are wired up, and the framework is now able to instantiate custom contexts without being aware of any feature provider implementation.

0 Response to “SharePoint Dependency Injection Approach”


  • No Comments

Leave a Reply