Search code examples
wcfdependency-injectiondatacontract

WCF data contract design with dependency injection


So I have a layered application that I am adding a WCF service interface on top of. The service is simply a facade with all of our business logic already existing in Business Objects (BOs) within the Business Logic Layer (BLL) which is a class library. Within the BLL we use constructor injection to inject dependencies into the BOs. This is all working with good unit testing, etc. On to the problem...

Ordinarily I'd simply create a set of Request/Response objects as DataContracts for each service method with the appropriate properties for the operation. If the operation required one of our "entities" to be passed either to or from the method, I'd simply define a property of that type and everything would be fine (all of our BOs are serializable). However when one of these "entities" is passed into a service method, WCF deserializes the object without ever invoking the constructors we've defined and, as a result, the dependencies don't resolve.

Let's use the case of a service method called CreateSomething. I'd normally define this as a service operation with a signature like:

CreateSomethingResponse CreateSomething(CreateSomethingRequest request);

CreateSomethingRequest would be a DataContract and have amongst its properties a property of type Something that represented the "entity" being passed into the service. Something, in this case, is a business object that expects to receive an instance of the ISomethingRepository interface from the DI container when instantiated - which, as I said above, does not happen when WCF deserializes the object on the server.

Option #2 is to remove the Something property from the DataContract and define each of the properties explicitly in my DataContract then inside my service method, create a new instance of the Something class, letting the container inject the dependency, then map the property values from the DataContract object into the BO. And I can certainly do that but I am concerned about now having two places to make changes if, say, I want to add a property to the Something type. And, with a lot of properties, there's a lot of code duplication.

Has anyone crossed this bridge and, if so, can you share your thoughts and how you have or would approach this situation in your own applications? Thx!!!


Solution

  • Thanks, Ladislav, for your answer as you confirmed what was already in my head.

    What I ended up doing was to change my approach a little. I realized that my use of a business object, per se, was overkill and unnecessary. Or perhaps, just misdirected. When evaluating my requirements, I realized that I could "simplify" my approach and make everything work. By taking each logical layer in my application and looking at what data needed to pass between the layers, I found a design that works.

    First, for my business logic layer, instead of a business object, I implemented a Unit of Work object: SomethingManager. SomethingManager is tied to my root Something entity so that any action I want to perform on or with Something is done through the SomethingManager. This includes methods like GetById, GetAll, Save and Delete.

    The SomethingManager class accepts two objects in its constructor: an IValidator<Something> and an ISomethingRepository. These will be injected in by the IoC container. The former lets me perform all of the necessary validation using whatever framework we chose (initially the Validation Application Block) and the latter gives me persistance ignorance and abstracts the use of Linq-to-SQL today and makes upgrading to EF4 much easier later on.

    For my service layer, I've wired the IoC container (Unity in this case) into WCF so the service instance is created by the container. This allows me to inject an instance of ISomethingManager into my service. Using the interface, I can break the dependency and easily unit test the service class. Plus, because the container is injecting the ISomethingManager instance, it is constructing it and will automatically resolve it's dependencies.

    I then created DataContracts to represent how the data should appear when transferred across the wire via the service. Each Request/Response object contains these DataContracts as DataMembers rather than referencing my entity classes (or BOs) directly. It is up to the service method to map the data coming from or going to the Business Logic Layer (via ISomethingManager) - using AutoMapper to make this clean and efficient.

    Back in the data layer, I've simply extended the generated entity classes by defining a partial class that implements the desired interface from the BLL. For instance, the Something L2S entity has a partial defined that implements ISomething. And ISomething is what the SomethingManager (and ISomethingManager interface) and ISomethingRepository work with making it very easy to query the database and pass the L2S entity up the chain for the service layer to consume and pass on (without the service layer having any knowledge or dependency on the L2S implementation).

    I appreciate any comment, questions, criticisms or suggestions anyone has on this approach.