FilterAttribute Property Injection in Autofac MVC 3 Integration

by Alex Meyer-Gleaves 24 March 2011 - 3:56 AM

The current mechanism for performing property injection on FilterAttribute instances via the ExtensibleActionInvoker had to be removed recently due to a rather nasty bug. These are the notes that Nick provided outlining the problem he discovered (possibly with the help of the exciting new Whitebox profiler).

Because the filters passed from the base action invoker also include the controller, property injection happens on the controller itself several times as the filters are processed.

The filter attributes also included in the collection may also be singletons cached by MVC, and so it is quite likely that dependencies may be overwritten with those from a concurrently executing request.

In all this behaviour is probably too risky to reliably support.

Removed property injection routine. (Breaking change.)

I have replaced the old mechanism using an approach that leverages the improved dependency injection support added to MVC 3 (this will be in the next release). To make use of property injection for your filter attributes all you will need to do is call the RegisterFilterProvider method on the ContainerBuilder before building your container and providing it to the AutofacDependencyResolver.

ContainerBuilder builder = new ContainerBuilder();

builder.RegisterControllers(Assembly.GetExecutingAssembly());
builder.Register(c => new Logger()).As<ILogger>().InstancePerHttpRequest();
builder.RegisterFilterProvider();

IContainer container = builder.Build();
DependencyResolver.SetResolver(new AutofacDependencyResolver(container));

Then you can add properties to your filter attributes and any matching dependencies that are registered in the container will be injected into the properties. For example, the action filter below will have the ILogger instance that was registered above injected. Note that the attribute itself does not need to be registered in the container.

public class CustomActionFilter : ActionFilterAttribute
{
    public ILogger Logger { get; set; }

    public override void OnActionExecuting(ActionExecutingContext filterContext)
    {
        Logger.Log("OnActionExecuting");
    }
}

The same simple approach applies to the other filter attribute types such as authorization attributes.

public class CustomAuthorizeAttribute : AuthorizeAttribute
{
    public ILogger Logger { get; set; }

    protected override bool AuthorizeCore(HttpContextBase httpContext)
    {
        Logger.Log("AuthorizeCore");
        return true;
    }
}

After applying the attributes to your actions as required your work is done.

[CustomActionFilter]
[CustomAuthorizeAttribute]
public ActionResult Index()
{
    // ...
}

To make this work I added a custom FilterAttributeFilterProvider implementation. The custom filter provider delegates the job of collecting the filters to the base class. Once the filters have been retrieved by the base class, the ILifetimeScope for the current HTTP request is retrieved and used to perform property injection on the filters. The false passed to the base FilterAttributeProvider constructor sets the cacheAttributeInstances parameter to ensure that attribute instances are not cached. Allowing the attribute instances to be cached would result in race conditions and other unexpected behaviour.

/// <summary>
/// Defines a filter provider for filter attributes that performs property injection.
/// </summary>
public class AutofacFilterAttributeFilterProvider : FilterAttributeFilterProvider
{
    /// <summary>
    /// Initializes a new instance of the <see cref="AutofacFilterAttributeFilterProvider"/> class.
    /// </summary>
    /// <remarks>
    /// The <c>false</c> constructor parameter passed to base here ensures that attribute instances are not cached.
    /// </remarks>
    public AutofacFilterAttributeFilterProvider() : base(false)
    {
    }

    /// <summary>
    /// Aggregates the filters from all of the filter providers into one collection.
    /// </summary>
    /// <param name="controllerContext">The controller context.</param>
    /// <param name="actionDescriptor">The action descriptor.</param>
    /// <returns>
    /// The collection filters from all of the filter providers with properties injected.
    /// </returns>
    public override IEnumerable<Filter> GetFilters(ControllerContext controllerContext, ActionDescriptor actionDescriptor)
    {
        var filters = base.GetFilters(controllerContext, actionDescriptor).ToArray();
        var lifetimeScope = AutofacDependencyResolver.Current.RequestLifetimeScope;

        if (lifetimeScope != null)
            foreach (var filter in filters)
                lifetimeScope.InjectProperties(filter.Instance);

        return filters;
    }
}

The RegisterFilterProvider method has been added to the ContainerBuilder using an extension method. This method will register the AutofacFilterAttributeFilterProvider using the IFilterProvider interface that MVC uses when asking the dependency resolver for filter providers. Following the instructions outlined in Brad Wilson’s post on the subject of dependency injection and filters, I made sure that the default FilterAttributeFilterProvider instance is removed from the static collection of providers.

/// <summary>
/// Registers the <see cref="AutofacFilterAttributeFilterProvider"/>.
/// </summary>
/// <param name="builder">The container builder.</param>
public static void RegisterFilterProvider(this ContainerBuilder builder)
{
    if (builder == null) throw new ArgumentNullException("builder");

    foreach (var provider in FilterProviders.Providers.OfType<FilterAttributeFilterProvider>().ToArray())
        FilterProviders.Providers.Remove(provider);

    builder.RegisterType<AutofacFilterAttributeFilterProvider>()
        .As<IFilterProvider>()
        .SingleInstance();
}

If you were using the old mechanism you will have breaking changes to contend with, but as you can see it should be easy to get back on track again.

Tags: ,

Autofac | Web Development

View Page Injection in Autofac ASP.NET MVC 3 Integration

by Alex Meyer-Gleaves 28 December 2010 - 11:31 PM

The increased support for dependency injection in ASP.NET MVC 3 includes the ability to have your view pages created by your favourite container.

Historically, these classes have not had access to dependency injection/service location functionality, because their creation was buried deep inside the implementation of the view engine. In MVC 3, we have updated the built-in view engines to attempt to create the view page classes via the service locator; if that fails, it will fall back to using Activator.CreateInstance, just like in previous versions of MVC.

Because the view pages are dynamically compiled at runtime a few restrictions have been imposed; you cannot use constructor injection and your view pages must inherit from a custom base class.

The problem is that your .aspx/.ascx/.cshtml/.vbhtml files are converted into classes at runtime by the ASP.NET Build Manager (in collaboration with build providers). When those classes are auto generated, they are auto generated only with a single parameterless constructor.

We looked at auto-generating constructors, but it turns out that we don't actually know enough about the base class when we're generating the code to actually do any reflection on it, so it's not really possible for us to look at the base class and determine which constructors it may or may not have.

Happy that these limitations are not going to pose any serious problems let’s move onto the Autofac integration. Time for yet another uninspiring example, but one that should be easy to follow and doesn’t require too much typing on my part. Imagine that we have a service that provides common company information such as a copyright that we need to display on all our view pages.

public interface ICompanyInformation
{
    string Copyright { get; }
}

There is of course an implementation of the service that returns the dynamic copyright information (you were warned about the example).

public class CompanyInformation : ICompanyInformation
{
    public string Copyright
    {
        get { return string.Format("Copywrong &copy; {0} ACME Corporation", DateTime.Now.Year); }
    }
}

In the application start event we build our container and register the service along with our controllers. We also add a registration source called ViewRegistrationSource.

ContainerBuilder builder = new ContainerBuilder();
builder.Register(c => new CompanyInformation()).As<ICompanyInformation>().InstancePerHttpRequest();
builder.RegisterControllers(Assembly.GetExecutingAssembly());
builder.RegisterSource(new ViewRegistrationSource());

IContainer container = builder.Build();
DependencyResolver.SetResolver(new AutofacDependencyResolver(container));

The registration source is where all the magic happens. A registration source allows you to create an adapter that will dynamically provide a registration for a service. We know that MVC will ask the container for an instance of the view page before it attempts to create it itself, so we can use the registration source to make sure that the container always knows how to provide such an instance. Below is the implementation of the registration source for those that are interested in the details.

public class ViewRegistrationSource : IRegistrationSource
{
    public IEnumerable<IComponentRegistration> RegistrationsFor(Service service, Func<Service, IEnumerable<IComponentRegistration>> registrationAccessor)
    {
        var typedService = service as IServiceWithType;

        if (typedService != null && IsSupportedView(typedService.ServiceType))
            yield return RegistrationBuilder.ForType(typedService.ServiceType)
                .PropertiesAutowired()
                .InstancePerHttpRequest()
                .CreateRegistration();
    }

    public bool IsAdapterForIndividualComponents
    {
        get { return false; }
    }

    static bool IsSupportedView(Type serviceType)
    {
        return serviceType.IsAssignableTo<WebViewPage>() 
            || serviceType.IsAssignableTo<ViewPage>()
            || serviceType.IsAssignableTo<ViewMasterPage>()
            || serviceType.IsAssignableTo<ViewUserControl>();
    }
}

If the requested service inherits from one of the supported view base classes, the RegistrationBuilder.ForType helper is used to build the registration. The registration also makes sure that property injection is performed and that the lifetime is scoped to the HTTP request. The Razor view base class WebViewPage is supported, along with the WebForms base classes ViewPage, ViewMasterPage and ViewUserControl.

To get properties on the view page that can be injected by the container, you need to slot your own base class into the inheritance hierarchy. This is as simple as creating an abstract class that derives from WebViewPage or WebViewPage<T> when using the Razor view engine.

public abstract class CustomViewPage : WebViewPage
{
    public ICompanyInformation CompanyInformation { get; set; }
}

If you are using the WebForms view engine in your MVC project you would derive from the ViewPage or ViewPage<T> class instead.

public abstract class CustomViewPage : ViewPage
{
    public ICompanyInformation CompanyInformation { get; set; }
}

The last thing you need to do is ensure that your actual view page inherits from your custom base class. This can be achieved using the @inherits directive inside your .cshtml file for the Razor view engine.

@inherits Example.Views.Shared.CustomViewPage

@{
    ViewBag.Title = "Home Page";
}

<h2>@ViewBag.Message</h2>
<p>
    This is the page content.
</p>
<p>
    @CompanyInformation.Copyright
</p>

When using the WebForms view engine you set the Inherits attribute on the @ Page directive inside you .aspx file instead.

<%@ Page Language="C#" MasterPageFile="~/Views/Shared/Site.Master" Inherits="Example.Views.Shared.CustomViewPage"%>

<asp:Content ID="Content1" ContentPlaceHolderID="TitleContent" runat="server">
    Home Page
</asp:Content>

<asp:Content ID="Content2" ContentPlaceHolderID="MainContent" runat="server">
    <h2><%: ViewBag.Message %></h2>
    <p>
        This is the page content.
    </p>
    <p>
        <%= CompanyInformation.Copyright %>
    </p>
</asp:Content>

Making your custom base class inherit from the generic WebViewPage<T> or ViewPage<T> class allows you to provide your strongly typed model as the generic type parameter. You can of course choose to leave the generic type parameter in your base class open making it more reusable.

public abstract class CustomViewPage<T> : WebViewPage<T>
{
    public ICompanyInformation CompanyInformation { get; set; }
}

You simply provide the model type as the closing generic parameter in the type declared in the @inherits or Inherits attribute of the page.

@inherits Example.Views.Shared.CustomViewPage<Example.Models.CustomModel> 

Taking advantage of view page injection is a very simple matter. No doubt you will have much more creative uses for this than the simplified example shown here.

Tags: ,

Autofac | Web Development

Model Binder Injection in Autofac ASP.NET MVC 3 Integration

by Alex Meyer-Gleaves 7 December 2010 - 11:30 PM

The Autofac MVC integration supported model binder injection in the MVC 2 version, but improvements in the dependency injection support offered by MVC 3 has allowed the implementation to be made cleaner. ASP.NET MVC 3 introduces the IModelBinderProvider interface that allows the implementer to determine what model binder should be used for a particular type.

Developers who implement this interface can optionally return an implementation of IModelBinder for a given type (they should return null if they cannot create a binder for the given type).

Let’s start by looking at how the model binder injection is configured in the MVC integration. You first create a class that implements IModelBinder like you would when creating any other model binder in MVC. Next you apply the ModelBinderType attribute provided as part of the integration to indicate what types the model binder supports binding. The simple example below declares that the model binder supports binding for string types.

[ModelBinderType(typeof(string))]
public class StringBinder : IModelBinder
{
    public override object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
    {
        // Do implementation here.
    }
}

You then use the RegisterModelBinders extension method on the ContainerBuilder to register all the IModelBinder types that are present in one or more assemblies.

ContainerBuilder builder = new ContainerBuilder();
builder.RegisterModelBinders(Assembly.GetExecutingAssembly());

The interesting part about the implementation of the assembly scanning is that it finds the types the model binder supports through the ModelBinderType attributes and then adds this information as metadata to the registration.

public static IRegistrationBuilder<object, ScanningActivatorData, DynamicRegistrationStyle>
    RegisterModelBinders(this ContainerBuilder builder, params Assembly[] modelBinderAssemblies)
{
    return builder.RegisterAssemblyTypes(modelBinderAssemblies)
        .Where(type => typeof(IModelBinder).IsAssignableFrom(type))
        .As<IModelBinder>()
        .InstancePerHttpRequest()
        .WithMetadata(AutofacModelBinderProvider.MetadataKey, type => 
            (from ModelBinderTypeAttribute attribute in type.GetCustomAttributes(typeof(ModelBinderTypeAttribute), true)
             from targetType in attribute.TargetTypes
            select targetType).ToList());
}

You must also remember to register the AutofacModelBinderProvider using the RegisterModelBinderProvider extension method. This is Autofac's implementation of the new IModelBinderProvider interface.

builder.RegisterModelBinderProvider();

The constructor of the AutofacModelBinderProvider requests that an IEnumerable<Meta<Lazy<IModelBinder>>> be provided. When the GetBinder method is called through the IModelBinderProvider interface, the list of Meta<T> about the components is queried to locate any potential matches based on the types stored in the metadata. The Lazy<T> part of dependency makes sure that we do not actually create an instance of the IModelBinder until it is actually needed.

public IModelBinder GetBinder(Type modelType)
{
    Meta<Lazy<IModelBinder>> modelBinder = _modelBinders
        .FirstOrDefault(binder => ((List<Type>)binder.Metadata[MetadataKey]).Contains(modelType));
    return (modelBinder != null) ? modelBinder.Value.Value : null;
}

This dynamic approach to handling model binder injection removes the need for a special wrapper around each IModelBinder component, and avoids having to register this wrapper directly into the static ModelBinders.Binders dictionary.

Tags:

Autofac | Web Development

ASP.NET MVC 3 Beta integration for Autofac

by Alex Meyer-Gleaves 4 November 2010 - 2:38 AM

I have just checked into trunk a first pass at the ASP.NET MVC 3 Beta integration for Autofac. In hope of simplifying the requirements for those getting started with the integration I wanted to prevent the need to:

The code below is an example of all you would need to put into the application start event to get up and running.

ContainerBuilder builder = new ContainerBuilder();
builder.RegisterControllers(Assembly.GetExecutingAssembly());
builder.Register(c => new Logger()).As<ILogger>().InstancePerHttpRequest();

IContainer container = builder.Build();
DependencyResolver.SetResolver(new AutofacDependencyResolver(container));

The core piece of the integration is the AutofacDependencyResolver. This is an implementation of the IDependencyResolver interface that Brad Wilson outlines in his blog post series on ASP.NET MVC 3 Service Location. The interface requires you to implement two simple methods: GetService and GetServices. When no service is found GetService should return null, and GetServices should return an empty IEnumerable<object>. The implementation of these methods ends up being straight forward (ignoring for now the code related to managing the CurrentLifetimeScope).

public object GetService(Type serviceType)
{
    return CurrentLifetimeScope.IsRegistered(serviceType) ? CurrentLifetimeScope.Resolve(serviceType) : null;
}

public IEnumerable<object> GetServices(Type serviceType)
{
    Type enumerableServiceType = typeof(IEnumerable<>).MakeGenericType(serviceType);
    object instance = CurrentLifetimeScope.Resolve(enumerableServiceType);
    return ((IEnumerable)instance).Cast<object>();
}

When MVC needs to create a controller it will ask the DependencyResolver for an instance. The AutofacDependencyResolver returns the controllers that are registered in the container it was provided. These are usually registered using the RegisterControllers method on the ContainerBuilder as shown in the first code sample. There is no longer a need to create a class that derives from the DefaultControllerFactory for the sole purpose of returning controller instances. This means the AutofacControllerFactory is no longer required and has been removed.

The Autofac MVC integration has always supported the concept of a HTTP request lifetime scope. This means that the lifetime of a service can be scoped to the current HTTP request. The ILogger service registration in the sample code above uses the InstancePerHttpRequest method to indicate that the same instance of the logger service should be used for all dependency resolutions that occur during the current HTTP request. To make sure that the nested lifetime scope that Autofac creates for each request is disposed, it needs to be notified when the request has ended.

The only reliable way to do this is to create a HTTP module that subscribes to the EndRequest event of the HttpApplication. To register a HTTP module you need to add an entry to the web configuration file, which is something that I was hoping to avoid. Rick Strahl outlines one way of achieving programmatic registration of a module in his Dynamically hooking up HttpModules post, but for the integration this would require the user to manually add the code to their HttpApplication instance (by default called MvcApplication).

It turns out that there is in fact another way to programmatically register a module. The Microsoft.Web.Infrastructure.dll assembly that ships with the ASP.NET Web Pages installer (AspNetWebPages.msi) contains a rather helpful class called DynamicModuleUtility. It has a single method called RegisterModule that accepts a Type for the module to register. You can only call this helper from a method that is marked as pre application start code as defined by the PreApplicationStartMethodAttribute applied to an assembly. The same trick is used in System.Web.Pages.dll to register the new WebPageHttpModule. Phil Haack has a blog post that talks about the PreApplicationStartMethodAttribute and some other interesting new ASP.NET 4 features in greater detail if you are keen to know more. You need to install ASP.NET Web Pages before installing ASP.NET MVC 3 so we know the assembly with this helpful little gem will be available.

In the Autofac integration we first needed to add the assembly attribute.

[assembly: PreApplicationStartMethod(typeof(PreApplicationStartCode), "Start")]

This points to a static class that contains a single static method called Start. Inside this method we call the DynamicModuleUtility to register the RequestLifetimeModule that will informs us when the HTTP request has ended. There is no need to ever call this class directly but unfortunately, it and the method must be public. That is why we have the EditorBrowsable attribute being applied in order to hide the class from the editor. Not really that much work to save a user from having to dive into the web configuration file.

[EditorBrowsable(EditorBrowsableState.Never)]
public static class PreApplicationStartCode
{
    private static bool _startWasCalled;

    public static void Start()
    {
        if (_startWasCalled) return;

        _startWasCalled = true;
        DynamicModuleUtility.RegisterModule(typeof(RequestLifetimeModule));
    }
}

There is a new interface in the MVC 3 integration called ILifetimeScopeProvider. The HTTP module RequestLifetimeModule shown above actually implements this interface and is the default implementation used by the AutofacDependencyResolver. You can see from the AutofacDependencyResolver code shown at the start of the post that the resolutions are happening from the CurrentLifetimeScope property.

internal ILifetimeScope CurrentLifetimeScope
{
    get
    {
        if (_lifetimeScopeProvider == null)
            _lifetimeScopeProvider = GetRequestLifetimeModule();
        return _lifetimeScopeProvider.GetLifetimeScope(_container, _configurationAction);
    }
}

You can add your own ILifetimeScopeProvider implementation to the container that is passed to the AutofacDependencyResolver if you want to replace the HTTP request based lifetime behaviour. The AutofacDependencyResolver will attempt to retrieve it from the container during its constructor. Because the RequestLifetimeModule is the default ILifetimeScopeProvider and an instance was already created by ASP.NET when the module was initialised, we can go and grab that from the HttpModuleCollection of the current HttpApplication.

static ILifetimeScopeProvider GetRequestLifetimeModule()
{
    HttpModuleCollection httpModules = HttpContext.Current.ApplicationInstance.Modules;
    for (int index = 0; index < httpModules.Count; index++)
    {
        if (httpModules[index] is RequestLifetimeModule)
            return (RequestLifetimeModule)httpModules[index];
    }
    throw new InvalidOperationException(string.Format(
        AutofacDependencyResolverResources.HttpModuleNotLoaded, typeof(RequestLifetimeModule)));
}

None of the model binding code has been moved into the new integration yet. I am hoping that this can be refactored to use the new IModelBinderProvider interface. This is only a first pass based on a new approach so it is likely that some of this will change. I have certainly found the exercise interesting enough that I thought it was worth sharing the start of the journey.

Tags: ,

Autofac | Web Development

Introducing Action Injection with Autofac ASP.NET MVC Integration

by Alex Meyer-Gleaves 16 May 2010 - 2:33 AM

There are currently two main approaches to performing dependency injection, Constructor Injection and Setter Injection. The more popular of the two approaches is Constructor Injection. The dependencies that a type has are made obvious because they must be supplied in order to construct an instance. This also makes it easier for you to ensure that a newly instantiated object is in a valid state. When working with a type the constructor is usually the first thing that you come into contact with.

With Setter Injection, also known as Property Injection, it is much more difficult to tell what the dependencies are when looking at the type from the outside. Setter Injection is most useful when you have no control over the instantiation of the type that requires the dependencies to be injected. This is a common scenario for ASP.NET WebForms where the activation of a Page instance is performed by the runtime. You do not have an opportunity to take over the activation process, and the first chance you have to perform dependency injection is when you are provided with an existing instance of Page. In this case you have no choice but to inject the dependencies into the type via its properties.

ASP.NET MVC has many extensibility points and is very flexible. It provides you with the opportunity to take over the creation of your Controller instances by creating your own factory that implements IControllerFactory, or more commonly by deriving from the DefaultControllerFactory and overriding the GetControllerInstance method. This makes it possible for your controllers to take advantage of Constructor Injection, and is exactly what the Autofac ASP.NET MVC Integration does. When it comes to unit testing your controller classes, it becomes very easy to see what dependencies it has, and to provide mock implementations for those dependencies.

An issue that is often raised in regards to Constructor Injection is what some people like to call Constructor Bloat. This may indicate that you are not following the Single Responsibility Principle and that some refactoring may be in order. The number of constructor parameters that would be considered too many would no doubt vary depending on who you ask. In the case of ASP.NET MVC controllers the number of constructor dependencies is more likely to be higher than for other classes. The level of responsibility for a controller is usual greater than what you would expect for an ordinary internal component. This is the result of mapping an external view of the application (URL based) onto an internal representation (controller based).

It turns out that both Nicholas Blumhardt and I found ourselves shifting some of these dependencies out of the controller’s constructor and into the action methods that actually require them. We were both fairly surprised to find out that the other had independently been doing exactly the same thing, and at this point discussed if there was something wrong with the approach because it seemed that no one else was doing it. Surely all good ideas have already been done so this one must be bad. I personally feel that having dependencies injected into your action method should not feel like a foreign concept because that is exactly what MVC is already doing for you with your existing parameters.

For lack of any official term that I am aware of, Action Injection is what I am calling this particular approach to dependency injection in ASP.NET MVC. The more I play around with this approach the more I like it. Your constructor is provided the dependencies that are shared by all actions in your controller, and each individual action can request any additional dependencies that it needs. Now when writing unit tests for your actions there is no need to provide mock implementations for dependencies that your action will not be interacting with. The end result is less mocks in your unit tests and a clear indication of the action’s actual dependencies.

Nick and I have decided to test out the idea of Action Injection in the Autofac ASP.NET MVC Integration. The changes are only in the source code at the moment and have not yet been included in a release. I mentioned earlier that MVC is very extensible and the process for invoking your action methods is no different. It is possible to replace the default behaviour by creating your own IActionInvoker. The easiest way to do this is by deriving from the AsyncControllerActionInvoker class and overriding the appropriate methods. A controller can be requested to use your custom action invoker by assigning an instance to the controller's ActionInvoker property. The current source includes a registration extension that allows you to register an IActionInvoker instance that will be assigned to a controller as it is activated. There is a default IActionInvoker implementation called ExtensibleActionInvoker that allows dependencies to be injected into your action methods. It can also do Setter Injection on your filters but that is a topic for another post. As the name suggests, you can extend this class and add any additional behaviour that you require. Registering controllers in the HttpApplication start would look something like this.

ContainerBuilder builder = new ContainerBuilder();

builder.RegisterType<ExtensibleActionInvoker>().As<IActionInvoker>();
builder.RegisterControllers(Assembly.GetExecutingAssembly()).InjectActionInvoker();

// Register other services.

IContainer container = builder.Build();
_containerProvider = new ContainerProvider(container);

ControllerBuilder.Current.SetControllerFactory(new AutofacControllerFactory(_containerProvider));

I will not go into further detail on the implementation at this point because it may be tweaked a little before being released. Instead, let us look at an example of how we could make our action dependencies clearer using Action Injection. The NotifyController class below has action methods that send the current user a message using different delivery methods.

public class NotifyController
{
    public NotifyController(ILogger logger, 
        IEmailNotifier emailNotifier, 
        ISmsNotifier smsNotifier, 
        IMessengerNotifier messengerNotifier)
    {
        // Implementation.
    }
    
    public ActionResult Email(string message)
    {
        // Implementation.
    }
    
    public ActionResult Sms(string message)
    {
        // Implementation.
    }

    public ActionResult Messenger(string message)
    {
        // Implementation.
    }
}

There are three action methods on this controller and four dependencies that must be provided through the constructor. To unit test any of the action methods all four of the dependencies will need to be mocked. In this controller the ILogger instance is required by all action methods, but the remaining notifier dependencies are each required only by one action method. The controller could be refactored so that it takes the one ILogger dependency through its constructor, and each action could take its particular notifier dependency through a method parameter. Here is an example of how the refactored code would look.

public class NotifyController
{
    public NotifyController(ILogger logger)
    {
        // Implementation.
    }
    
    public ActionResult Email(string message, IEmailNotifier emailNotifier)
    {
        // Implementation.
    }
    
    public ActionResult Sms(string message, ISmsNotifier smsNotifier)
    {
        // Implementation.
    }

    public ActionResult Messenger(string message, IMessengerNotifier messengerNotifier)
    {
        // Implementation.
    }
}

Now when testing the action methods we only ever need to provide two mock services. There is no need to provide additional mock services that will never be used. Assuming we only had one unit test per action and setup our mocks inside each unit test, we would have halved the number of mocks required, taking the total from twelve down to six. That certainly seems like an improvement to me.

I would be interested to know what you think about this idea. Is it totally crazy or could there be something to it? Maybe you too have already been doing this and could share how it has been working out for you.

Tags: ,

Autofac | Web Development

Making Self-Hosting with Autofac WCF Integration easier

by Alex Meyer-Gleaves 16 May 2010 - 1:48 AM

Thinking about the sample I recently posted for shelf-hosting WCF Services with the Autofac WCF Integration, I decided that the boilerplate code for configuring the Service Behavior could be moved into an extension method on the ServiceHost instead. I have checked in some code that will extend ServiceHostBase with a new method called AddDependencyInjectionBehavior. There are two overloads of the method, one that takes a generic argument for the service contract type, and another that allows you to provide a Type for the service contract in case you are configuring your WCF Services in some sort of latebound manner. Both overloads of the method require an IContainer instance.

host.AddDependencyInjectionBehavior<IEchoService>(container);
host.AddDependencyInjectionBehavior(typeof(IEchoService), container);

As you can see from the updated sample below, the extension method makes the code considerably more concise, and will save you from having to write your own helper method that can be reused with your different WCF Services.

ContainerBuilder builder = new ContainerBuilder();
builder.Register(c => new Logger()).As<ILogger>();
builder.Register(c => new EchoService(c.Resolve<ILogger>())).As<IEchoService>();

using (IContainer container = builder.Build())
{
    Uri address = new Uri("http://localhost:8080/EchoService");
    ServiceHost host = new ServiceHost(typeof(EchoService), address);

    host.AddServiceEndpoint(typeof(IEchoService), new BasicHttpBinding(), string.Empty);

    host.AddDependencyInjectionBehavior<IEchoService>(container);

    host.Description.Behaviors.Add(new ServiceMetadataBehavior {HttpGetEnabled = true, HttpGetUrl = address});
    host.Open();
    
    Console.WriteLine("The host has been opened.");
    Console.ReadLine();

    host.Close();
    Environment.Exit(0);
}

The extension method will be available in the next release of Autofac. If you want to try it out without grabbing the latest Autofac source, the code below should give you a feel for how it works. You do not need to provide the service implementation type to the extension method because it can be retrieved from the ServiceHost instance. The Type instance that you provide in the ServiceHost constructor surfaces as the ServiceHost.Description.ServiceType property and can be used directly in the extension method.

public static class ServiceHostExtensions
{
    public static void AddDependencyInjectionBehavior<T>(this ServiceHostBase serviceHost, IContainer container)
    {
        AddDependencyInjectionBehavior(serviceHost, typeof(T), container);
    }

    public static void AddDependencyInjectionBehavior(this ServiceHostBase serviceHost, Type contractType, IContainer container)
    {
        IComponentRegistration registration;
        if (!container.ComponentRegistry.TryGetRegistration(new TypedService(contractType), out registration))
        {
            string message = string.Format("The service contract type '{0}' has not been registered in the container.", contractType.FullName);
            throw new ArgumentException(message);
        }

        AutofacDependencyInjectionServiceBehavior behavior = new AutofacDependencyInjectionServiceBehavior(
            container, serviceHost.Description.ServiceType, registration);
        serviceHost.Description.Behaviors.Add(behavior);
    }
}

Nothing fancy here but that should make self-hosting a little easier.

Tags: ,

Autofac | Web Services

Self-Hosting WCF Services with the Autofac WCF Integration

by Alex Meyer-Gleaves 7 May 2010 - 12:14 AM

A question came up recently in the Autofac group about how to use the WCF Integration when self-hosting WCF Services. This post provides a quick demonstration of how to handle the self-hosting scenario and should be enough to get you started. The example is a rather unimaginative web service that echoes back a message.

First declare the interface and implementation for a logger that the WCF Service will take as a dependency in its constructor. This is a simple logger that will log the message sent to the WCF Service out to the console.

public interface ILogger
{
    void Write(string message);
}

public class Logger : ILogger
{
    public void Write(string message)
    {
        Console.WriteLine(message);
    }
}

Next you need to define the contract and implementation for the WCF Service. Nothing interesting here other than our dependency being requested through the constructor of the WCF Service implementation.

[ServiceContract]
public interface IEchoService
{
    [OperationContract]
    string Echo(string message);
}

public class EchoService : IEchoService
{
    private readonly ILogger _logger;

    public EchoService(ILogger logger)
    {
        _logger = logger;
    }

    public string Echo(string message)
    {
        _logger.Write(message);
        return message;
    }
}

Now we can create a Console Application that will configure the container and host our WCF Service.

ContainerBuilder builder = new ContainerBuilder();
builder.Register(c => new Logger()).As<ILogger>();
builder.Register(c => new EchoService(c.Resolve<ILogger>())).As<IEchoService>();

using (IContainer container = builder.Build())
{
    Uri address = new Uri("http://localhost:8080/EchoService");
    ServiceHost host = new ServiceHost(typeof(EchoService), address);
    host.AddServiceEndpoint(typeof(IEchoService), new BasicHttpBinding(), string.Empty);

    IComponentRegistration registration;
    if (!container.ComponentRegistry.TryGetRegistration(new TypedService(typeof(IEchoService)), out registration))
    {
        Console.WriteLine("The service contract has not been registered in the container.");
        Console.ReadLine();
        Environment.Exit(-1);
    }

    host.Description.Behaviors.Add(new AutofacDependencyInjectionServiceBehavior(container, typeof(EchoService), registration));
    host.Description.Behaviors.Add(new ServiceMetadataBehavior {HttpGetEnabled = true, HttpGetUrl = address});
    host.Open();
    
    Console.WriteLine("The host has been opened.");
    Console.ReadLine();

    host.Close();
    Environment.Exit(0);
}

Here we have added an IServiceBehavior called AutofacDependencyInjectionServiceBehavior that will add a custom IInstanceProvider to the DispatchRuntime of each endpoint’s EndpointDispatcher. That is a bit of a mouth full but basically means that Autofac will use the WCF extensibility points to provide WCF Service instances that have their dependencies injected.

In this example the WCF Service is exposed on an endpoint that uses the BasicHttpBinding but you can use any type of endpoint that you like. I have added a ServiceMetadataBehavior in this example that exposes the WSDL for the WCF Service at http://localhost:8080/EchoService?wsdl. You can use this address to create a client proxy and send test messages that are hopefully more creative than my example.

Tags: ,

Autofac | Web Services

Autofac 2.0 Podcast

by Alex Meyer-Gleaves 6 April 2010 - 12:47 AM

Make sure you have a listen to Nicholas Blumhardt talking about Autofac 2 on the Talking Shop Down Under podcast.

It's Inversion of Control Time! This week Nick Blumhardt talks about IoC containers in general, the problems with the service locator pattern and why constructor injection is considered a better choice, a little about how MEF and Autofac differ in purpose and a lot about Autofac 2's new features.

Nick was also a guest on .NET Rocks! last year, and that episode is definitely worth listening to as well.

The .NET dudes talk to Nicholas Blumhardt about Autofac, an IoC container that uses lambda expressions in C# 3.0 to create components.

Keep spreading the good word Nick!

Tags:

Autofac

Registering open generic types in Autofac 1.4

by Alex Meyer-Gleaves 3 January 2010 - 12:34 AM

UPDATE (5 January 2010): This feature has now been added to the Autofac 1.4 codebase. I had intended to get this one directly into the codebase but Nick and I got our wires crossed, and I ended up posting it as an extension instead. Regardless, this post remains a valid example of extending Autofac 1.4. The RegisterClosedTypesOf method will appear on the ContainerBuilder in the next 1.4 maintenance release. Until then you can use the extension below to register your open generic types.

This is a follow up to my recent post about writing an extension for registering open generic interface types in Autofac 2. The feature described in the first post, along with support for open generic classes, has since been added to the Autofac 2 codebase. You can grab the current 2.1 preview release on the download page and test it out.

I personally feel that the latest preview version of Autofac 2 is stable enough to start using, but I know that even when released not everyone will be able to adopt the new version as soon as they would like. For that reason I have decided to write a similar extension for Autofac 1.4 that supports both open generic interfaces and classes.

Before I move onto the code I would like to draw a distinction between this feature and the RegisterGeneric method found on instances of the the ContainerBuilder class in Autofac 1.4. The RegisterGeneric method allows you to register an open generic type and have a closed generic type created for you when requested. For example, registering List<> and then resolving List<string> will cause Autofac to create a new List<string> instance for you. The difference is that the RegisterGeneric feature does not locate existing types that close the open generic type being registered.

In the unit test below we are ensuring that a closing type is provided for an open generic interface. It is similar to that from the original post, except the extension method is called RegisterClosedTypesOf and extends ContainerBuilder instances instead of RegistrationBuilder instances. The extension method also has a parameter for the assembly that will be scanned to find the closing types. This is different from the Autofac 2 implementation were the assembly is provided to the RegisterAssemblyTypes method, and the containing types are filtered using a delegate provided to the RegistrationBuilder.

[Test]
public void RegisterClosedTypesOf_OpenGenericInterfaceTypeProvided_ClosingGenericTypesRegistered()
{
    ContainerBuilder builder = new ContainerBuilder();
    Assembly assembly = typeof(ICommand<>).Assembly;
    builder.RegisterClosedTypesOf(typeof(ICommand<>), assembly);
    IContainer container = builder.Build();

    Assert.That(container.Resolve<ICommand<SaveCommandData>>(), Is.InstanceOf<SaveCommand>());
    Assert.That(container.Resolve<ICommand<DeleteCommandData>>(), Is.InstanceOf<DeleteCommand>());
}

In addition to the types I used for unit testing in the previous post, there are two new types used for the testing of open generic classes.

/// <summary>
/// An abstract open generic base class.
/// </summary>
public abstract class Message<T>
{
}

/// <summary>
/// A class that closed the open generic type.
/// </summary>
public class StringMessage : Message<string>
{
}

The new message types are used in the next unit test to make sure that support for open generic classes is working.

[Test]
public void RegisterClosedTypesOf_OpenGenericAbstractClassTypeProvided_ClosingGenericTypesRegistered()
{
    ContainerBuilder builder = new ContainerBuilder();
    Assembly assembly = typeof(Message<>).Assembly;
    builder.RegisterClosedTypesOf(typeof(Message<>), assembly);
    IContainer container = builder.Build();

    Assert.That(container.Resolve<Message<string>>(), Is.InstanceOf<StringMessage>());
}

Now that we know how the extension method is used we can move onto the implementation.

/// <summary>
/// Extension methods for the <see cref="ContainerBuilder"/> class.
/// </summary>
public static class ContainerBuilderExtensions
{
    /// <summary>
    /// Scans the types in an assembly and registers those that support any base or interface that closes the 
    /// provided open generic service type.
    /// </summary>
    /// <param name="builder">The container builder being extended.</param>
    /// <param name="openGenericServiceType">The open generic interface or base class type for which implementations will be found.</param>
    /// <param name="assembly">The assembly to scan for the matching types.</param>
    public static void RegisterClosedTypesOf(this ContainerBuilder builder, Type openGenericServiceType, Assembly assembly)
    {
        if (openGenericServiceType == null) throw new ArgumentNullException("openGenericServiceType");

        if (!(openGenericServiceType.IsGenericTypeDefinition || openGenericServiceType.ContainsGenericParameters))
        {
            throw new ArgumentException(
                string.Format("The type '{0}' is not an open generic class or interface type.",
                              openGenericServiceType.FullName));
        }

        foreach (Type candidateType in assembly.GetTypes())
        {
            Type closedServiceType;
            if (findAssignableTypeThatCloses(candidateType, openGenericServiceType, out closedServiceType))
            {
                builder.Register(candidateType).As(closedServiceType);
            }
        }
    }

    /// <summary>
    /// Looks for an interface on the candidate type that closes the provided open generic interface type.
    /// </summary>
    /// <param name="candidateType">The type that is being checked for the interface.</param>
    /// <param name="openGenericServiceType">The open generic service type to locate.</param>
    /// <param name="closedServiceType">The type of the closed service if found.</param>
    /// <returns>True if a closed implementation was found; otherwise false.</returns>
    private static bool findAssignableTypeThatCloses(Type candidateType, Type openGenericServiceType, out Type closedServiceType)
    {
        closedServiceType = null;

        if (candidateType.IsAbstract) return false;

        foreach (Type interfaceType in getTypesAssignableFrom(candidateType))
        {
            if (interfaceType.IsGenericType && interfaceType.GetGenericTypeDefinition() == openGenericServiceType)
            {
                closedServiceType = interfaceType;
                return true;
            }
        }

        return false;
    }

    /// <summary>
    /// Returns the interface and base types that given a type is assignable from.
    /// </summary>
    /// <param name="candidateType">The type to find assignable types for.</param>
    /// <returns>A list of the assignable interface and base types.</returns>
    private static IEnumerable<Type> getTypesAssignableFrom(Type candidateType)
    {
        foreach (Type interfaceType in candidateType.GetInterfaces())
        {
            yield return interfaceType;
        }

        Type nextType = candidateType;
        while (nextType != typeof(object))
        {
            yield return nextType;
            nextType = nextType.BaseType;
        }
    }
}

After the usual sort of argument checking the types in the assembly are enumerated and tested to see if they close the open generic type. The findAssignableTypeThatCloses method does the work of locating a possible match and returns a value indicating if a match was found. When a match is found the out parameter is assigned the closing type that was located, and the registration is added to the ContainerBuilder. The getTypesAssignableFrom method helps out by returning all the interface and base types assignable from the type it is provided.

That is all that is needed to add support for open generic types in Autofac 1.4.

ContainerBuilderExtensions.cs (3.71 kb)

ContainerBuilderExtensionsTests.cs (3.93 kb)

Tags:

Garage Sale Code | Microsoft .NET | Autofac

Registering open generic interface types in Autofac

by Alex Meyer-Gleaves 19 December 2009 - 7:22 PM

UPDATE (22 December 2009): I have submitted a patch to Nick and this feature has now been added to the Autofac V2 codebase. While including the patch Nick added support for open generic classes and renamed the extension method to AsClosedTypesOf. This post will be left in its current form and remains a valid example of extending Autofac.

There has been some discussion lately around connecting an open generic type to its implementation types in a number of different dependency injection containers including StructureMap and Unity:

It looks like this is not the first time this scenario has been discussed:

I also recently noticed a posting on the Autofac Google Group asking if it was possible for Autofac to automatically register an open generic interface type against its implementations. Nicholas Blumhardt (the creator of Autofac and all round nice guy) suggested that this would be easy to implement using the new RegisterAssemblyTypes method found on the ContainerBuilder in the upcoming V2 release. Since I have been meaning to take a closer look at the preview of Autofac V2, I decided that having a look into solving this would be a good way for me to dip my toes into the water. I decided to limit the scope to supporting only automatic registrations for open generic interface types. There is no doubt you could use the extensibility provided by the RegisterAssemblyTypes method to take things much further and add features like those supported in the Unity Auto Registration library.

Time to introduce some types that will be used in the unit tests. First is the open generic interface type.

/// <summary>
/// An open generic interface type.
/// </summary>
public interface ICommand<T>
{
    void Execute(T data);
}

Next we have a couple of simple types that will be used as the generic type parameters.

/// <summary>
/// A type to use as a generic parameter.
/// </summary>
public class SaveCommandData
{
}

/// <summary>
/// A type to use as a generic parameter.
/// </summary>
public class DeleteCommandData
{
}

To keep things interesting I decided to include an abstract base class that implements the ICommand interface.

/// <summary>
/// An abstract base class that implements the open generic 
/// interface type.
/// </summary>
public abstract class CommandBase<T> : ICommand<T>
{
    public abstract void Execute(T data);
}

There will be two command implementations. The first will directly implement the ICommand interface.

/// <summary>
/// A command class that directly implements the open 
/// generic interface type.
/// </summary>
public class SaveCommand : ICommand<SaveCommandData>
{
    public void Execute(SaveCommandData data)
    {
    }
}

The second will implement the ICommand interface by inheriting from the CommandBase<T> abstract class.

/// <summary>
/// A command class that implements the open generic interface 
/// type by inheriting from the abstract base class.
/// </summary>
public class DeleteCommand : CommandBase<DeleteCommandData>
{
    public override void Execute(DeleteCommandData data)
    {
    }
}

I will use the first unit test to define the name and signature of the extension method that be will added to the RegistrationBuilder. The extension method will be named WhereTypeClosesOpenGenericInterface and will be available on the RegistrationBuilder returned from the RegisterAssemblyTypes method. It will take a single parameter for the Type that represents the open generic interface type that automatic registrations will be created for.

This first unit test will actually ensure that passing a null value as the method parameter will result in an ArgumentNullException being thrown.

[Test]
public void WhereTypeClosesOpenGenericInterface_NullTypeProvided_ThrowsException()
{
    ContainerBuilder builder = new ContainerBuilder();
    Assert.Throws<ArgumentNullException>(() => builder.RegisterAssemblyTypes(typeof(ICommand<>).Assembly).
        WhereTypeClosesOpenGenericInterface(null));
}

The next unit test will ensure that passing a non-generic type into the method will result in an ArgumentException being thrown.

[Test]
public void WhereTypeClosesOpenGenericInterface_NonGenericTypeProvided_ThrowsException()
{
    ContainerBuilder builder = new ContainerBuilder();
    Assert.Throws<ArgumentException>(() => builder.RegisterAssemblyTypes(typeof(ICommand<>).Assembly).
        WhereTypeClosesOpenGenericInterface(typeof(SaveCommandData)));
}

Another simple unit test will ensure that passing in a closed generic type will also result in an ArgumentException being thrown.

[Test]
public void WhereTypeClosesOpenGenericInterface_ClosedGenericTypeProvided_ThrowsException()
{
    ContainerBuilder builder = new ContainerBuilder();
    Assert.Throws<ArgumentException>(() => builder.RegisterAssemblyTypes(typeof(ICommand<>).Assembly).
        WhereTypeClosesOpenGenericInterface(typeof(ICommand<SaveCommandData>)));
}

The last of the boring unit tests ensures that passing in an open generic type that is not an interface will again result in an ArgumentException being thrown.

[Test]
public void WhereTypeClosesOpenGenericInterface_NonInterfaceOpenGenericTypeProvided_ThrowsException()
{
    ContainerBuilder builder = new ContainerBuilder();
    Assert.Throws<ArgumentException>(() => builder.RegisterAssemblyTypes(typeof(ICommand<>).Assembly).
        WhereTypeClosesOpenGenericInterface(typeof(List<>)));
}

Now onto the interesting unit test that will ensure our registrations are wired up correctly. We use our new WhereTypeClosesOpenGenericInterface extension method and pass it the ICommand<> open generic interface type. Obviously when we resolve a closed generic interface type we except the returned instance to be the type that implements it. In the case of the SaveCommand the implementation of the interface is direct, and with the DeleteCommand the implementation of the interface is through its inheritance of CommandBase<T>.

[Test]
public void WhereTypeClosesOpenGenericInterface_OpenGenericInterfaceTypeProvided_ClosingGenericTypesRegistered()
{
    ContainerBuilder builder = new ContainerBuilder();
    builder.RegisterAssemblyTypes(typeof(ICommand<>).Assembly)
        .WhereTypeClosesOpenGenericInterface(typeof(ICommand<>));
    IContainer container = builder.Build();

    Assert.That(container.Resolve<ICommand<SaveCommandData>>(), Is.TypeOf<SaveCommand>());
    Assert.That(container.Resolve<ICommand<DeleteCommandData>>(), Is.TypeOf<DeleteCommand>());
}

Finally we arrive at the implementation code. I looked at the StructureMap implementation before writing this to keep an eye out for details that I might have otherwise forgotten. Doing so seemed like a good idea considering their code has already been put through its paces. Take a quick look over the code and I will explain what is going on below.

/// <summary>
/// Extension methods for the <see cref="RegistrationBuilder{TLimit,TActivatorData,TRegistrationStyle}"/> class.
/// </summary>
public static class RegistrationBuilderExtensions
{
    /// <summary>
    /// Specifies that a type from a scanned assembly is registered if it implements an interface
    /// that closes the provided open generic interface type.
    /// </summary>
    /// <typeparam name="TLimit">Registration limit type.</typeparam>
    /// <typeparam name="TRegistrationStyle">Registration style.</typeparam>
    /// <typeparam name="TScanningActivatorData">Activator data type.</typeparam>
    /// <param name="registration">Registration to set service mapping on.</param>
    /// <param name="openGenericInterfaceType">The open generic interface type for which implementations will be found.</param>
    /// <returns>Registration builder allowing the registration to be configured.</returns>
    public static RegistrationBuilder<TLimit, TScanningActivatorData, TRegistrationStyle>
        WhereTypeClosesOpenGenericInterface<TLimit, TScanningActivatorData, TRegistrationStyle>(
            this RegistrationBuilder<TLimit, TScanningActivatorData, TRegistrationStyle> registration, Type openGenericInterfaceType)
        where TScanningActivatorData : ScanningActivatorData
    {
        if (openGenericInterfaceType == null)
        {
            throw new ArgumentNullException("openGenericInterfaceType");
        }

        if (!(openGenericInterfaceType.IsGenericTypeDefinition || openGenericInterfaceType.ContainsGenericParameters) || !openGenericInterfaceType.IsInterface)
        {
            throw new ArgumentException("The type '" + openGenericInterfaceType.FullName + "' is not an open generic interface type.");
        }

        return registration.Where(candidateType => findInterfaceThatCloses(candidateType, openGenericInterfaceType) != null)
            .As(candidateType => findInterfaceThatCloses(candidateType, openGenericInterfaceType));
    }

    /// <summary>
    /// Looks for an interface on the candidate type that closes the provided open generic interface type.
    /// </summary>
    /// <param name="candidateType">The type that is being checked for the interface.</param>
    /// <param name="openGenericInterfaceType">The open generic interface type to locate.</param>
    /// <returns>The type of the interface if found; otherwise, <c>null</c>.</returns>
    private static Type findInterfaceThatCloses(Type candidateType, Type openGenericInterfaceType)
    {
        if (candidateType.IsAbstract) return null;

        foreach (Type interfaceType in candidateType.GetInterfaces())
        {
            if (interfaceType.IsGenericType && interfaceType.GetGenericTypeDefinition() == openGenericInterfaceType)
            {
                return interfaceType;
            }
        }

        return (candidateType.BaseType == typeof(object)) 
            ? null
            : findInterfaceThatCloses(candidateType.BaseType, openGenericInterfaceType);
    }
}

First the parameter for the open generic interface type is checked to ensure that it is not null and that it is indeed an open generic interface type. Next we use the RegistrationBuilder instance that is being extended to determine what types we want registered and what their service mappings will be. The important methods on the RegistrationBuilder that enable this are the Where and As methods. The Where method takes a predicate that is used to filter the list of scanned types down to only those you are interested in registering. The As method is used to provide the service mappings for the types that got included for registration after the filter was applied.

The Func<Type,bool> predicate provided to the Where method on the RegistrationBuilder instance utilizes a private method named findInterfaceThatCloses. When the findInterfaceThatCloses method is called it will look for an interface on the type provided as the first parameter, that matches the type provided as the second parameter. In our case we are passing in the candidate type that was provided by the assembly scanning process, and the open generic interface type we are interested in matching. When no matching interface is found null is returned. When used in the delegate parameter provided to the Where method for filtering we check for the return from findInterfaceThatCloses being not null, and use the actual type returned from the method for the delegate parameter provided to the As method for mapping the services. We know that when the As method is called it will only be provided with types that were included by the filter, so we need not worry about receiving a type that does not implement the interface at this point.

The implementation of the findInterfaceThatCloses method ensures that only types which are not abstract are checked for matching interfaces. It then iterates through the available interfaces and checks if any match the open generic interface type provided. If no matching interface is found we recursively check if the type’s base class implements the interface until we reach a type that inherits directly from object.

As you can see Nick has done a great job making Autofac extensible, allowing additional requirements for your container to be met with very little effort on your part. I think the next version of Autofac is shaping up nicely and I look forward to posting more about it in the future.

Tags:

Garage Sale Code | Microsoft .NET | Autofac

About the author

Alex Meyer-Gleaves I'm a Technical Architect living in Australia (that island like continent in the southern hemisphere). I love Microsoft .NET and C#. I hate early mornings, slow drivers and Lotus Notes.

Google Shared

 

Month List

Recent Posts

Recent Comments

Comment RSS

Links

Disclaimer

The opinions expressed herein are my own personal opinions and do not represent my employer's view in anyway.

© Copyright 2010