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.
Recent Comments