object GetInstance(Type serviceType)

This method is used for retrieving a single instance. For containers that support keyed instances, this should return the "default" instance (see more on default below). This method delegates to the GetInstance overload that accepts key and passes in a null key.

Requirements:
  • This method MUST NOT return null. It MUST return either an instance that implements the requested type or throw an ActivationException.
  • No other exception type is allowed (except for the usual CLR rules for things like ThreadAbortException).

TService GetInstance<TService>()

This method is used for retrieving a strongly typed single instance. It should behave similar to object GetInstance(Type serviceType)

Requirements:

object GetInstance(Type serviceType, string key)

This method is used for retrieving a keyed instance from the container.

Requirements:
  • This method MUST NOT return null. It MUST return either an instance that implements the requested type or throw an ActivationException.
  • No other exception type is allowed (except for the usual CLR rules for things like ThreadAbortException).
  • The implementation should be designed to expect a null for the string key parameter, and MUST interpret this as a request to get the "default" instance for the requested type. This meaning of default varies from locator to locator. For example in Castle Windsor, the first instance registered will always be the default. In the case of Unity, the default instance is the instance that was specifically registered without a key. A string of length 0 is considered to be different from a null, and implementers are free to choose what a string of length 0 as a key means.

TService GetInstance<TService>(string key)

This method is used for retrieving a strongly typed keyed instance. It should behave similar to object GetInstance(Type serviceType, string key)

Requirements:

IEnumerable<object> GetAllInstances(Type serviceType)

This method retrieves all the instances from the locator of the specificed type.

Requirements:
  • If no instances of the requested type are available, this method MUST return an enumerator of length 0 instead of throwing an exception.
  • If an exception occurs while activating instances during enumeration, this method SHOULD throw an ActivationException and abort the enumeration. However, it may also choose to simply skip that object and continue enumerating.

IEnumerable<TService> GetAllInstances<TService>()

This method retrives a strongly typed collection from the locator of the specified type.

Requirements

Overload Behavior

A call to:
    object IServiceLocator.GetInstance(serviceType)
MUST be exactly equivalent to a call to:
    object IServiceLocator.GetInstance(serviceType, null)
A call to:
    TService IServiceLocator.GetInstance<TService>()
MUST be exactly equivalent to a call to:
    (TService)IServiceLocator.GetInstance(typeof(TService), null)

A call to:
    TService IServiceLocator.GetInstance<TService>(key)
MUST be exactly equivalent to a call to:
    (TService)IServiceLocator.GetInstance(typeof(TService), key)
A call to:
    IEnumerable<TService> IServiceLocator.GetAllInstances<TService>()
Must be exactly equivalent to a call to:
    IEnumerable<object> IServiceLocator.GetAllInstances(typeof(TService))

with the exception that the objects returned by the enumerator are already cast to type TService.

Throwing ActivationException

  • When throwing an ActivationException, the message string is explicitly undefined by this specification; the adapter implementors may format this message in any way they choose.
  • When throwing an ActivationException, the original exception MUST be returned as the value of the InnerException property.

ServiceLocatorImplBase

This class is not part of the specification; consumers should only reference the IServiceLocator interface. ServiceLocatorImplBase is provided as a convenience for implementors of IServiceLocator. It implements the correct overload semantics and exception wrapping behavior defined above. You just need to implement the two protected methods DoGetInstance and DoGetAllInstances and the rest will just work. In addition, the two protected methods FormatActivationExceptionMessage and FormatActivateAllExceptionMessage are provided if you wish to customize the error message reported in the exceptions.

Why is ActivationException a partial class?

Implementing ISerializable for exceptions is a .NET best practice for the desktop CLR. However, I anticipate a port to Silverlight for this code - many containers are already supporting Silverlight beta 2 or are about to. Silverlight does not support classic binary serialization. By making this a partial class and segregating the serialization details into a separate file, a future Silverlight port can simply leave the .Desktop.cs file out of the project and the incompatible code will be seamlessly removed.

Last edited Sep 30, 2008 at 8:24 AM by gblock, version 6

Comments

jimmyzimms Dec 17, 2008 at 5:51 PM 
khebbie,

You can always extend this interface to support the extra abilities you need. The rationale behind this interface is to abstract Getting Objects from a container, not how to build up a container.

khebbie Nov 24, 2008 at 10:11 AM 
This is a really great initiative, and very useful!
However one of the things I miss in the interface is the ability to register an instance through the interface.
When doing unit testing, it is very useful to Ie. register a test double of some sort