Since we were working on a multi-tentant solution with Umbraco, we needed a solution as Umbraco's membership did not support multi-tenant out of the box. Discussed in a previous article(Umbraco Multi-Tenant Membership), we chose Brock Allen's Membership Reboot. For the integration with Umbraco multi-tenant, there were three primary tasks: dependency injection update, tenant configuration, and content integration. Here we discuss the issues associated with dependency injection (DI).
Umbraco and Dependency Injection
In a previous article (Umbraco and StructureMap), we discussed the difficulties we encountered integrating Umbraco with StructureMap. It was largely a troubleshooting exercise as we encountered multiple issues. Given the issues we encountered, we were not too excited when we discovered that the Membership Reboot was using NInject. A developer integrating with Brock Allen with Umbraco will face the issue of how to handle the DI whether they are currently using DI or not. If you are already using NInject with Umbraco, this is probably a non-issue. If you are not using DI, then you may want to review the article Umbraco and StructureMap for potential solutions to issues that you may encounter.
The Membership Reboot uses NInject by default (in the sample web project). It has a pretty compelling reason. NInject allows for hijacking the application start to create the Container prior to application initialization. This allows NInject to do things like Constructor Injection with Http Modules (HttpApplicationInitializationHttpModule). This removes the anti-pattern of ObjectFactory.CreateInstance that you find in our Http Modules. In other words, when we removed the NInjectWebCommon startup class provided by Membership Reboot, we realized we had a technical debt. We liked the concept of constructor injection on the modules and handlers, but we did not feel we had the time to address this at this time. So I expect we will revisit this in the near future.
Simple Conversion of NInject Specific Calls
Once we removed the NInject initialization, we just need to add back in the DI initialization code for specific classes. The following was the conversion from NInject to Structure Map:
var unique = new UniquePerRequestLifecycle();
.Use(ctx => ctx.GetInstance<IMembershipRebootConfigFactory>().GetMembershipRebootConfiguration()));
x => x.For<IUserAccountRepository>().LifecycleIs(unique).Use<DefaultUserAccountRepository>());
.Use(db => new DefaultMembershipRebootDatabase("MembershipReboot")));
Container.Configure(x => x.For<AuthenticationService>().Use<SamAuthenticationService>());
Container.Configure(x => x.For<IUserAccountQuery>().LifecycleIs(unique).Use<DefaultUserAccountRepository>());
Container.Configure(x => x.For<UserAccountService>().Use<UserAccountService>());
So the conversion from NInject to Structure Map for the Membership Reboot turned out to be straight forward. It also taught about a new way to create the container which we would like to try in the future.