InfoQ

InfoQ

News

My Bookmarks

Login or Register to enable bookmarks for unlimited time.

The content has been bookmarked!

There was an error bookmarking this content! Please retry.

Injecting Implementation Dependencies into WCF Services

Posted by Hartmut Wilms on Jan 08, 2008

Sections
Development,
Enterprise Architecture
Topics
Web Services ,
.NET Framework ,
.NET
Tags
Dependency Injection ,
WCF

A very popular concept of implementing WCF services is to use a layered approach that consists of a service, a business logic and a data access layer. The dependencies between these layers might be injected at runtime via dependency injection containers.

The Service Architecture Concept Model as outlined by Don Smith proposes a WCF service facade which provides a published interface/contract that is implemented by components of a business (logic) layer. Those components have in turn dependencies with data access components of the resource access layer.

The dependencies between the layers are normally hard-coded within the service and component implementations, complicating unit tests. Pablo M. Cibraro shows how to inject component dependencies by implementing a WCF Dependency Injection Behavior. In Pablo's approach ObjectBuilder is used as the Dependency Injection Container whereas Oran Dennison makes use of Spring.NET in his approach to WCF Service Dependency Injection.

Oran presents the following setup of dependencies within his service implementation code:

[ServiceContract]
public interface IServiceContract {
[OperationContract]
...
}

public class ServiceLayer : IServiceContract {
IBusinessLogic _businessLogic;

public ServiceLayer(IBusinessLogic businessLogic) {
_businessLogic = businessLogic;
}
...
}

public interface IBusinessLogic {
...
}

public class BusinessLogic : IBusinessLogic {
IDataAccess _dataAccess;

public BusinessLogic(IDataAccess dataAccess) {
_dataAccess = dataAccess;
}
...
}

public interface IDataAccess {
...
}

public class DataAccess : IDataAccess {
...
}

The service implementation has a dependency with the business logic component, which has in turn a dependency with the data access component. The hard-wired variant of setting up all dependencies would look like this:

return new ServiceLayer(new BusinessLogic(new DataAccess()));

Dependency injection containers basically inject those dependencies by providing a mapping of interfaces to implementation classes within a configuration. This configuration might be changed at runtime, for instance in order to run unit tests that use mock implementations. Pablo explains:

Quite easy, the only requirement [for a dependency injection container] is the mapping, otherwise the container will not know how to create instances of the interfaces. Now, let's move forward to try configuring this in WCF using a behavior as extensibility point. WCF supports an extension called IInstanceProvider that controls the lifecycle of a WCF service instance. We will use one this provider to hook up our custom code and inject the dependencies at runtime.

public class DIInstanceProvider : IInstanceProvider {   
[...]


public object GetInstance(InstanceContext instanceContext, Message message) {
DependencyContainer container = new DependencyContainer();
foreach (TypeMapping typeMapping in this.typeMappings) {
container.RegisterTypeMapping(typeMapping.TypeRequested, typeMapping.TypeToBuild);
}
return
container.Get(this.serviceType);
}
[...]
}

The DIInstanceProvider has then to be plugged into the dispatcher runtime by an IServiceBehavior. The type mappings are configured within a new WCF configuration section, which is implemented by a BehaviorExtensionElement that reads the mappings from the configuration file and passes them to the DIServiceBehavior instance. Pablo's sample configuration including type mappings looks like this:

<behaviors>

      <serviceBehaviors>

        <behavior name="Behaviors1">

          <dependencyInjection>

            <typeMappings>

              <add name="DataAccess" typeRequested="SampleService.ICustomerDataAccess, SampleService"

                    typeToBuild="SampleService.CustomerDataAccess, SampleService"/>

              <add name="BusinessComponent" typeRequested="SampleService.ICustomerBusinessComponent, SampleService"

                    typeToBuild="SampleService.CustomerBusinessComponent, SampleService"/>

            typeMappings>

          dependencyInjection>

        behavior>

      serviceBehaviors>   

behaviors>

Pablo has published his sample code. It should be fairly easy to adapt the code to Oran's approach or to any other dependency injection container, e.g. Castle Windsor.

There is a Windsor Facility for WCF by Glenn Goodrich Posted
  1. Back to top

    There is a Windsor Facility for WCF

    by Glenn Goodrich

    Ayende has already written a WCF facility that registers the service on the Windsor container. Once it's registered, you can (of course) inject all the dependencies you want. Also, if you register any other classes that implement IServiceBehavior, they will be added to all the services registered with Windsor automatically. Very cool.

    Check it out here.

    Hope this is useful.

    Glenn

Educational Content

New-age Transactional Systems - Not Your Grandpa's OLTP

John Hugg discusses high volume transaction processing applications with high and low frequency profiles, and how VoltDB can be used for that purpose.

Cool Code

Kevlin Henney examines code samples to see what can be learned from them starting from the premise that one won’t write great code unless he knows how to read it.

Collaboration: At the Extremities of Extreme

Jason Ayers share the observations he made watching a team of developers collaborating in real time on the same code base, pushing XP, pair programming and continuous integration to their extremes.

Yesod Web Framework

Michael Snoyman presents Yesod, a web framework written in Haskell and containing a web server, templating, ORM, libraries (templating, gravatar, etc.).

Transactions without Transactions

Richard Kreuter and Kyle Banker on how to avoid classical RDBMS transactional systems by using compensation mechanisms, transactional messaging or transactional procedures.

Attila Szegedi on JVM and GC Performance Tuning at Twitter

Attila Szegedi talks about performance tuning Java and Scala programs at Twitter: how to approach GC problems, the importance of asynchronous I/O, when to use MySQL/Cassandra/Redis, and much more.

10 tips on how to prevent business value risk

One category of risk that project teams need to ensure they address is business value failure – delivering a product that fails to provide value for the business investor.

Interview: Software Systems Architecture: Working With Stakeholders Using Viewpoints and Perspectives

InfoQ spoke to the authors of Software Systems Architecture on a couple of new topics, the System Context viewpoint and Agile, which have been added to the second edition.