|
This article is based on Dependency Injection in .NET by Mark Seeman, to be published
Fall 2010. It is being reproduced here by permission from Manning Publications. Manning early access books and ebooks are sold exclusively through Manning. Visit
the book's page for more information.
You can get an instant 40% discount on this MEAP edition by just clicking on the
book cover image. Use promo code egghead40. |
Windows Communication Foundation (WCF) is one of the most extensible parts of the
Base Class Library (BCL). While it is fairly easy to get started writing WCF
services, the myriad of extensibility points can make it hard to find just the
one you need. This is also the case when it comes to DI.
NOTE
A joke claims that WCF is really an acronym for Windows Complication Foundation.
There’s a certain degree of truth in that claim.
You could easily be led to believe that WCF does not support Constructor Injection.
If you implement a WCF service with Constructor Injection and no default constructor,
at runtime the WCF service host will throw a ServiceActivationException with
a message similar to this:
The service type provided could not be loaded as a service because it does not have
a default (parameter-less) constructor. To fix the problem, add a default constructor
to the type or pass an instance of the type to the host.
This message strongly indicates that a default constructor is required. The only
way out seems to be to pass an already created instance to the WCF host. However,
that raises several issues:
§ How can we do this if we host the service in Internet Information Server (IIS)?
§ This requires the service to run in a single InstanceContextMode, which is undesirable
for a number of
other reasons.
The good news is that the exception message is misleading. There are other ways to
enable Constructor Injection with WCF.
WCF extensibility
WCF has lots of extensibility points, but when it comes to DI we only need to know
about the IInstanceProvider interface and contract behaviors. A contract behavior
is a Seam in WCF that allows us to modify how a given contract (in other words,
a service) behaves.
IInstanceProvider is an interface that defines how service instances are created
(and released). Here is the interface definition in all its glory:
public interface IInstanceProvider
{
object GetInstance(InstanceContext instanceContext);
object GetInstance(InstanceContext instanceContext, Message message);
void ReleaseInstance(InstanceContext instanceContext, object instance);
}
The two GetInstance overloads are responsible for creating an appropriate service
instance, while ReleaseInstance provides a hook for cleaning up, if necessary.
The default implementation simply looks for a default constructor on the service
type, but we can replace it with one that uses DI. Figure 1 illustrates the overall
flow when a hosted service receives a message.

Figure 1 When a message (request) arrives for service operation, WCF determines which
CLR type will implement the service. It asks a ServiceHostFactory to create an
appropriate ServiceHost that can host the requested service. The ServiceHost
does its part by applying behaviors and creating the requested instance.
When you host a WCF service on IIS, a ServiceHostFactory is mandatory, although the
default implementation will be used if you don’t explicitly define an alternative.
If you host the service manually, a ServiceHostFactory may still be useful but
is not required because you can create the appropriate ServiceHost directly in
code.
When the ServiceHost applies behaviors, it picks them up from at least three different
places before aggregating them:
§ Attributes
§ .config file
§ In-memory objects
While we can define behaviors in attributes, it’s not a particularly attractive strategy
to use when it comes to DI because that means that we are compiling a particular
creation strategy with particular Dependencies into the code. The net result
is almost the same as if we had simple hard-coded the Dependencies directly in
the service, just in a much more convoluted way.
A configuration file may sound like the ultimate in flexibility but really is not
because it does not allow us to imperatively configure Dependencies if we should
like to do that.
In-memory objects give us the best flexibility because we can choose to create the
Dependencies directly in code or based on configuration settings. If we use a
DI Container, we get both options for free.
This means that we should create a custom ServiceHostFactory that creates instances
of a custom
ServiceHost that again can wire up the desired service with all its Dependencies.
You can create a set of general-purpose classes that do this based on your DI Container
of choice or use one of the already implemented reusable container-based ServiceHostFactories.
You can also create a specialized ServiceHostFactory for a particular service.
Because it provides the best illustration of the process, I have chosen a specialized
factory for the following example.
Example: wiring up a product management service
As an example, let us imagine that we have been asked to extend a commerce application
with a WCF-based service that exposes operations that allow other applications
to manage product data. This would allow us to hook up a rich client (we will
do that in a subsequent section) or a batch job to manage product data.
Introducing ProductManagementService
To keep the example simple, let us assume that we wish to expose simple Create, Read,
Update , and Delete (CRUD) operations. Figure 2 shows a diagram of the service
and associated Data Contracts.

Figure 2 The IProductManagementService is a WCF service that defines simple CRUD
operations on products. It uses the associated ProductContract and MoneyContract
to expose these operations. Although not shown in this diagram, all three types
are decorated with the usual WCF attributes: ServiceContract, OperationContract,
DataContract, and DataMember.
Since we already have an existing domain model, we wish to implement this service
by extending the domain model and expose its operations through this WCF contract.
The exact details are not important ; just note that we expand the abstract ProductRepository
class.
The domain model represents a product as the Entity Product, while the service contract
exposes its operations in terms of the DTO ProductContract. To map between these
two different types, we also introduce an interface called IContractMapper.
Entity vs. DTO
In the previous paragraph I just threw some more jargon at you, but let ’s briefly
review what is meant by Entity and DTO.
An Entity is a term from Domain-Driven Design1 that covers a Domain Object that has a long-term identity unrelated to a particular
object instance. This may sound abstract and theoretical, but it just means that
it represents an object that lives beyond arbitrary bits in memory. While any
.NET object instance has an in -memory address (identity), an Entity has an identity
that lives across process lifetimes. We often use databases and primary keys
to identify Entities and ensure that we can persist and read them even if the
host computer reboots.
The Domain Object Product is an Entity because the concept of a product has a much
longer lifetime than a single process and we use a Product ID to identify it
in the ProductRepository.
A Data Transfer Object2 (DTO), on the other hand, exists only for the purpose of being transferred from
one application tier to another. While an Entity may encapsulate a lot of behavior,
a DTO is just a structure of data without behavior.
When exposing a Domain Model to external systems, we often do it with services and
DTOs since we can never be sure that the other system can share our type system
(it may not even use .NET). In such situations, we always need to map between
the Entities and the DTOs.
The bottom line is that we end up with a service implementation with two Dependencies,
and since both are mandatory we wish to use Constructor Injection. Here is the
service’s constructor signature:
public ProductManagementService(ProductRepository repository, IContractMapper mapper)
So far we have been happily ignoring the elephant in the room: how do we get WCF
to correctly wire up an instance of ProductManagementService?
Wiring up ProductManagementService in WCF
As illustrated in figure 1, the Composition Root in WCF is the triplet of ServiceHostFactory,
ServiceHost and IInstanceProvider. To wire up a service with Constructor Injection,
we must supply custom implementations of all three.
TIP
You can write completely reusable implementations that wrap your favorite DI Container
in those three types and use it to implement IInstanceProvider. Many people have
already done that, so you can probably find a readymade set for your chosen DI
Container.
NOTE
In this example, I implement a hardwired container using Poor Man’s DI. I have chosen
to encapsulate the hardcoded dependencies in a custom container class to give
you a good idea about how you could create a reusable solution based on a particular
DI Container.
1 Evans, Eric. Domain-Driven Design. Tackling Complexity in the Heart of Software.
Addison-Wesley, 2004. p. 89. 2 Fowler, Martin, et al. Patterns of Enterprise Application Architecture. Addison-Wesley,
2003. p. 401.
Let us start with the custom ServiceHostFactory, which is our true entry point to
a WCF service. Listing 1 shows the implementation.
Listing 1 Custom ServiceHostFactory
public class CommerceServiceHostFactory : #1
ServiceHostFactory #1
{
private readonly ICommerceServiceContainer container;
public CommerceServiceHostFactory()
{
this.container = #2
new CommerceServiceContainer(); #2
}
protected override ServiceHost CreateServiceHost( #A
Type serviceType, Uri[] baseAddresses) #A
{
if (serviceType == typeof(ProductManagementService))
{
return new CommerceServiceHost( #3
this.container, #3
serviceType, baseAddresses); #3
}
return base.CreateServiceHost(serviceType, baseAddresses);
}
}
#1 Derive from ServiceHostFactory
#2 Create container instance
#A Override CreateServiceHost
#3 Create custom ServiceHost
The custom CommerceServiceHostFactory derives from ServiceHostFactory (#1) with the
single purpose of wiring up ProductManagementService instances. It will use a
custom CommerceServiceContainer to do the actual work, so it creates an instance
of the container in its constructor (#2). You can easily expand this example
to use a true DI Container by simply creating and configuring an instance of
that container instead.
When asked to create a ServiceHost, it returns a new CommerceServiceHost with the
configured container (#3) if the requested service type is appropriate.
The CommerceServiceHost is responsible for assigning appropriate behaviors to all
the service types it hosts. In our case, we only want to add a single behavior
that assigns the desired IInstanceProvider to the services. All this work we
can accomplish in the constructor shown in listing 2, and the base class will
take care of the rest for us.
Listing 2 Custom ServiceHost
public class CommerceServiceHost : ServiceHost #1
{
public CommerceServiceHost(ICommerceServiceContainer container,
Type serviceType, params Uri[] baseAddresses)
: base(serviceType, baseAddresses)
{
if (container == null) #A
{ #A
throw new #A
ArgumentNullException("container"); #A
} #A
var contracts = #2
this.ImplementedContracts.Values; #2
foreach (var c in contracts) #2
{
var instanceProvider = #3
new CommerceInstanceProvider( #3
container); #3
c.Behaviors.Add(instanceProvider); #4
}
}
}
#1 Derive from ServiceHost
#A Guard Clause
#2 Loop over contracts
#3 Create InstanceProvider
#4 Add InstanceProvider as behavior
The CommerceServiceHost class derives from ServiceHost (#1), which is a concrete
class that does all the heavy lifting for us.
In most cases, we will only host a single service type (in this particular case,
ProductManagementService) but we are allowed to host multiple services, which
means that we must add the IInstanceProvider to them all. The ImplementedContracts
property is a dictionary so we must loop over its Values (#2) to target them
all.
For each service type, we initialize a new instance of the custom CommerceInstanceProvider
class with the container (#3). Since it doubles as a behavior, we can add it
to the service’s Behaviors (#4).
The last part of our custom WCF triplet is the CommerceInstanceProvider that doubles
as both IInstanceProvider and IContractBehavior. It’s a very simple implementation
but, since it implements two different interfaces with complex signatures, it
can look a bit daunting if you see it in one go. I will rather show the code
a little at a time, but figure 3 provides an overview.

Figure 3 CommerceInstanceProvider implements both IInstanceProvider and IContractBehavior,
so we are required to implement seven methods, although we can leave three empty
and the other four as one-liners.
Listing 3 shows the class declaration and the constructor. Nothing much goes on here
apart from the use of Constructor Injection to inject the container. Normally,
we use Constructor Injection to announce to a DI Container that a class requires
some Dependencies, but here it is backwards as we inject the container itself.
This is normally a big code smell since it usually indicates intent to use the
Service Locator anti-pattern, but it is necessary here since we are implementing
the Composition Root.
Listing 3 CommerceInstanceProvider class declaration and constructor
public partial class CommerceInstanceProvider :
IInstanceProvider, IContractBehavior #1
{
private readonly ICommerceServiceContainer container; #2
#2
public CommerceInstanceProvider( #2
ICommerceServiceContainer container) #2
{ #2
if (container == null) #2
{ #2
throw new ArgumentNullException("container"); #2
} #2
#2
this.container = container; #2
} #2
}
#1 Implement WCF interfaces
#2 Constructor Injection
The CommerceInstanceProvider implements both IInstanceProvider and IContractBehavior
(#1). We supply the container through standard Constructor Injection (#2). In
this sample, we use the custom CommerceServiceContainer. However, replacing it
with a general-purpose DI Container is a trivial exercise.
The IInstanceProvider implementation in listing 4 is used by the WCF runtime to create
instances of the ProductManagementService class.
Listing 4 IInstanceProvider implementation
public object GetInstance(InstanceContext instanceContext, Message message)
{
return this.GetInstance(instanceContext); #A
}
public object GetInstance(InstanceContext instanceContext)
{
return this.container #1
.ResolveProductManagementService(); #1
}
public void ReleaseInstance(InstanceContext instanceContext,
object instance)
{
this.container.Release(instance); #2
}
#A Delegate to overload
#1 Use container to resolve
#2 Ask container to release
The WCF runtime invokes one of the GetInstance methods to get an instance of the
requested service type, so we simply ask the container to wire up the ProductManagementService
(#1) with all its required Dependencies.
When the service operation has completed, the WCF runtime is nice to ask us to release
the instance, and once again we delegate this work to the container (#2).
The other part of CommerceInstanceProvider is the IContractBehavior implementation.
The only reason we implement this interface is to allow us to add it to the list
of behaviors as shown in listing 2. All of the methods on the IContractBehavior
interface return void, so we can leave most of them empty as we do not need to
implement them.
Listing 5 shows the implementation of the only method we care about.
Listing 5 Core implementation of IContractBehavior
public void ApplyDispatchBehavior(
ContractDescription contractDescription, ServiceEndpoint endpoint, DispatchRuntime
dispatchRuntime)
{
dispatchRuntime.InstanceProvider = this; #1
}
#1 Tell the runtime about this
We only need to do one exceedingly simple thing in this method. The WCF runtime calls
this method and passes an instance of DispatchRuntime, which allows us to tell
it that it should be using this particular IInstanceProvider implementation (#1).
Recall that CommerceInstanceProvider also implements IInstanceProvider. The WCF
runtime now knows which IInstanceProvider to use and it can subsequently invoke
the GetInstance method shown in listing 4.
This seems like a lot of code to implement to enable DI for WCF and I have even yet
to show you the implementation of CommerceServiceContainer.
TIP
Remember that you can easily write reusable versions of these three classes that
wrap your favorite DI Container and package that implementation into a library.
Many developers have already done that, so you can likely find a suitable ready-made
library on the internet.
The container is the last piece of the WCF DI puzzle.
Implementing the specialized container
The CommerceServiceContainer is a specialized container with a single purpose of
wiring up the ProductManagementService class. Recall that this class requires
instances of ProductRepository and IContractMapper as Dependencies.
With the entire WCF infrastructure out of the way, the container is free to concentrate
on wiring up the dependency graph.
NOTE
Besides adhering nicely to the Single Responsibility Principle, this separation of
concerns should give you a good idea that you can replace this specialized container
with a general-purpose DI Container because there’s no WCFspecific code present.
The ResolveProductManagementService method wires up the instance with Poor Man’s
DI as shown in listing 6.
Listing 6 Resolving ProductManagementService
public IProductManagementService ResolveProductManagementService()
{
string connectionString = #1
ConfigurationManager.ConnectionStrings #1
["CommerceObjectContext"].ConnectionString; #1
ProductRepository repository = #2
new SqlProductRepository(connectionString); #2
IContractMapper mapper = new ContractMapper(); #3
return new ProductManagementService(repository, #4
mapper); #4
}
#1 Get connection string from config
#2 Create product repository
#3 Create contract mapper
#4 Return service
In a sense, when it comes to resolving a dependency graph, it often pays to work
our way backwards. We know we need to return an instance of ProductManagementService
with ProductRepository and IContractMapper instances (#4). The IContractMapper
instance is easy to create (#3), but the ProductRepository requires a bit more
work.
We wish to use SqlProductRepository (#2), but to do that we need a connection string
that we can read from the web.config file (#1).
If you wish to host the service in your own application, you can now do that by creating
a new instance of the CommerceServiceHostFactory class and invoke its CreateServiceHost
method with the correct parameters. It will return a CommerceServiceHost instance
that you can open and it will figure out the rest for you and host the ProductManagementService.
If, however, you wish to host the service on IIS, there’s one more step that you
must take.
Hosting ProductManagementService on IIS
On IIS, we do not manually create new instances of CommerceServiceHostFactory. Instead,
we must tell IIS to do it on our behalf. This can be done in an .svc file by
supplying the Factory attribute:
<%@ ServiceHost Factory = "Ploeh.Samples.CommerceService.CommerceServiceHostFactory,
[CA]Ploeh.Samples.CommerceService"
Service = "Ploeh.Samples.CommerceService.ProductManagementService"
%>
This .svc file instructs IIS to use CommerceServiceHostFactory every time it needs
to create an instance of the ProductManagementService class. It is a requirement
that the ServiceHostFactory in question has a default constructor, but this is
also the case in this example.
Enabling DI in WCF is harder than it should be, but at least it is possible and the
end result is entirely satisfactory. We can use whichever DI Container we would
like and we end up having a proper Composition Root.
Summary
Object Composition is one of three important dimensions of DI (the others being Lifetime
Management and Interception). Some frameworks make it easy for us. When writing
console applications and Windows clients (WPF or Windows Forms), we are more
or less in direct control of what is happening at the application’s entry point.
This provides us with a distinct and easily implemented Composition Root right
at the entry point.
Other frameworks like ASP.NET MVC or WCF make us work a little harder, but they still
provide the Seams we can use to define how the application should be composed.
In WCF, the Seam almost appears as if it is accidentally there. Although it is
somewhat more roundabout than implementing a single interface, we can still achieve
all the DI goodness we could wish for.