Skip to content

Instantly share code, notes, and snippets.

@ndc
Created September 5, 2018 07:46
Show Gist options
  • Save ndc/7334d459c3eb0be594aad3973a488cad to your computer and use it in GitHub Desktop.
Save ndc/7334d459c3eb0be594aad3973a488cad to your computer and use it in GitHub Desktop.
Setting up dependency injection in ASP.NET WebForms (example using SimpleInjector)
using System;
using System.Collections.Generic;
using System.Linq;
namespace MyWebformApp
{
public class ContainerServiceProvider : IServiceProvider, System.Web.Hosting.IRegisteredObject
{
public ContainerServiceProvider(IServiceProvider next, Func<Type, object> resolverFunc)
{
_next = next;
_resolver = resolverFunc;
System.Web.Hosting.HostingEnvironment.RegisterObject(this);
}
private readonly IServiceProvider _next;
private Func<Type, object> _resolver;
private readonly System.Collections.Concurrent.ConcurrentDictionary<Type, bool> _typesCannotResolve
= new System.Collections.Concurrent.ConcurrentDictionary<Type, bool>();
private const int TypesCannontResolveCacheCap = 100000;
public object GetService(Type serviceType)
{
if (_typesCannotResolve.ContainsKey(serviceType))
{
return DefaultCreateInstance(serviceType);
}
object result = null;
try
{
result = _resolver(serviceType);
}
catch (Exception)
{
// Ignore and continue
}
if (result != null) return result;
result = _next?.GetService(serviceType);
if (result != null) return result;
result = DefaultCreateInstance(serviceType);
if (result == null) return result;
// Cache it
if (_typesCannotResolve.Count < TypesCannontResolveCacheCap)
{
_typesCannotResolve.TryAdd(serviceType, true);
}
return result;
}
public void Stop(bool immediate)
{
System.Web.Hosting.HostingEnvironment.UnregisterObject(this);
}
protected virtual object DefaultCreateInstance(Type type)
{
return Activator.CreateInstance(
type,
System.Reflection.BindingFlags.Instance
| System.Reflection.BindingFlags.NonPublic
| System.Reflection.BindingFlags.Public
| System.Reflection.BindingFlags.CreateInstance,
null,
null,
null);
}
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
namespace MyWebformApp
{
public partial class Default : System.Web.UI.Page
{
public Default(IMyService dep)
{
_dependency = dep;
}
private IMyService _dependency;
protected void Page_Load(object sender, EventArgs e)
{
// ...
}
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Security;
using System.Web.SessionState;
namespace MyWebformApp
{
public class Global : System.Web.HttpApplication
{
public static SimpleInjector.Container Container => new SimpleInjector.Container();
private static object _webObjectActivatorLock = new object();
protected void Application_Start(object sender, EventArgs e)
{
Container.Register<IMyService, MyService>();
Container.Verify();
// lock it to avoid registering ContainerServiceProvider multiple times
lock (_webObjectActivatorLock)
{
HttpRuntime.WebObjectActivator = new ContainerServiceProvider(
HttpRuntime.WebObjectActivator,
serviceType => Container.GetInstance(serviceType));
}
}
}
}
<?xml version="1.0"?>
<configuration>
<!-- ... -->
<system.web>
<!-- ... -->
<compilation targetFramework="4.7.2"/>
<httpRuntime targetFramework="4.7.2"/>
<!-- ... -->
</system.web>
<!-- ... -->
</configuration>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment