This project is read-only.

How can I check if a type is registered in the container ?

Aug 28, 2012 at 1:37 AM

I have created the following extension method but wondered if there was an easier way

public static bool IsTypeRegistered(this Container container, Type type)
{
  return container.GetRegistration(type, false) != null;
}

Aug 28, 2012 at 11:47 AM
Edited Aug 28, 2012 at 11:48 AM

This is exactly the way to do it. Such a method is not included into the framework because it is really easy to write it yourself, but more importantly, you should usually not need to check the existence of a registration. Doing this often indicates a design flaw in your application. There are valid use cases (as yours might very well be), but in general, you don't need this.

In general, you should prevent any application code to take a dependency on the container (or even an abstraction over the container). A dependency on the container is an implementation of the Service Locator pattern, which is considered to be an anti-pattern:

"The problem with Service Locator is that it hides a class’ dependencies, causing run-time errors instead of compile-time errors, as well as making the code more difficult to maintain because it becomes unclear when you would be introducing a breaking change."

If you use this IsTypeRegistered method inside your application, it means are using the container (in)directly. Using such a method often means you have an optional dependency. The consumer of that dependency can do without it. This however doesn't mean that you need to check the container to see whether it is available.

There are a few options here.  The best is to simply make this dependency required by defining it as constructor argument and register a Null Object implementation in the container (an implementation with no logic). This removes the need for the service to do any checks at all about the availability of that dependency. It just always is there. It is needed for the consumer to work, but the consumer doesn't care whether it is a real or a fake implementation. You can simply register the no-op dependency as follows:

container.RegisterSingle<IDependency, NullDependency>();

Alternatively, when the dependency is a generic implementation, you can use the RegisterOpenGeneric extension method (of the SimpleInjector.Extensions.dll) to make a mapping for all closed generic implementations:

container.RegisterOpenGeneric(typeof(IDependency<,>), typeof(NullDependency<,>));

An alternative is to define the dependency as writable property on the consumer. This makes the property optional. This solution is useful in scenarios where the consuming class is part of some reusable framework or tool, where external developers are expected to configure the container for use in their application. In this situation you might not always want to force those developers to register a Null Object. Downside of this approach is that your consumer will need to check whether that property is null or not, but at least takes away the dependency to the container, which is quite problematic, as explained above. You can enable property injection on the consumer using the following registration:

container.Register<IDependency, RealDependency>();
container.Register<IConsumer, Consumer>();

// Enable explicit property injection
container.RegisterInitializer<Consumer>(consumer =>
{
    consumer.Dependency = container.GetInstance<IDependency>();
});

If this advice does not apply to your situation, please supply a bit more background information on how you are using this IsTypeRegistered method. Perhaps I will be able to give some feedback on the usage or the design of your application.

Marked as answer by dot_NET_Junkie on 11/4/2013 at 2:01 AM
Aug 28, 2012 at 10:52 PM
Edited Aug 28, 2012 at 11:20 PM

Thanks for taking the time to respond.

I completely agree with your response however in my situation I am writting a IDependencyResolver for the webapi framework using simpleinjector as the container.

The issue that started this post is that this method must return null if the service was not found

/// <summary>
/// Gets an instance of the given <paramref name="serviceType"/>. Must return <c>null</c>
/// if the service is not available (must not throw).
/// </summary>
/// <param name="serviceType">The object type.</param>
/// <returns>The requested object, if found; <c>null</c> otherwise.</returns>
object GetService(Type serviceType);

I have implemented this as follows

public object GetService(Type serviceType)
{
    return !_container.IsTypeRegistered(serviceType) 
        ? null 
        : _container.GetInstance(serviceType);
}

If you have any advice I would be glad to hear it.

On a related note, it appears that just querying the container for a service appears to add it to the registrations dictionary with a null instanceproducter, so using the above code in a webapi solution causes a whole bunch of additional entries in the registration dictionary as the framework queryies to see if you have registered (overriden) any of their internal services.

Aug 29, 2012 at 11:18 AM
Edited Aug 29, 2012 at 11:31 AM

There is an Integration Guide in the Simple Injector documentation. It contains a link to a Stack Overflow article about integrating Simple Injector with the new ASP.NET Web API. This article explains how to implement an IDependencyResolver. In short, the SimpleInjector.Container implements System.IServiceProvider (explicitly) which contains an GetService method that has the same contract as the IDependencyResolver.GetInstance method. In other words, you can simply call the container's GetService method:

IServiceProvider provider = _container;
return provider.GetService(serviceType);

Although your approach yields the same, calling just GetService is faster than calling both GetRegistration and GetInstance.

About your related note: I moved that question to this new thread.