How to pass objects between layers of abstaction in c#?
So, I have an application structured with the following layers:
As of now, I am not using any concept of Objects to get data from the bottom-most layer. I am simply using DataTables to get data out. I am not happy with this because it requires the Business Logic Layer to be aware of column names, etc.
In my Business Logic layer I have objects that are loaded from those DataTables and the service layer works with those objects via Collections of those objects.
Here's my question. If I wanted to have the Data Abstr开发者_JAVA技巧action Layer accept and reply with Objects, how do I avoid referencing the DAL from the Service Layer? I've read that object factories are one way and also I've read I could build object transformation functions and so on.
What is the best way you've successfully employed this? My ultimate goal is to provide pluggable DALs for different Database server vendors.
A standard approach, and one I take often, is to have a common library of object models representing my domain: Customer, Order, OrderLine, etc, that are shared across all layers.
Better still, don't share the types across layers, just share the interfaces and have a factory available when instances are required.
You can then have a pluggable DAL, but your DAL still needs to conform to the contract of returning an ICustomer.
This doesn't stop references from being required, a reference to at least the interfaces are needed - as someone else has commented, other references, for the strong types or factories, could then be factored out - such as with IoC/DI frameworks.
The way I see it: a commom model is a cross-cutting concern in your application design, and shouldn't be seen as breaking the layering.
Update: this is a very vague explanation of the solution, so I stand to have it built upon.
Update 2: and now of course to answer your question. A standard way to remove a reference to a DLL directly is to expose the contract via an interface, in your case a DAL method GetCustomers
, your Service Layer talks to the interface, but requests a DAL instance via a Dependency Injection / Inversion of Control framework, or more easily, a factory. I usually go the factory route for small apps, it involves another DLL. Service Layer will reference interfaces and factory, DAL will reference interface, factory will reference interface and DAL.
Define simple objects (or interfaces) in a "Common" assembly, and use those.
For this to work, all layers / assemblies that need to exchange data will need to reference this common assembly; because of that you'll want to make the common assembly very very lean in terms of it's dependencies - otherwise you'll pollute the rest of your app.
For a simple application, I like to...
- Use an ORM within my DAL to simplify data access (Entity Framework)
- Use the repository pattern for CRUD operations (Repository Pattern)
- Use the repository pattern as an abstraction of the DAL, mapping ORM's object to DTOs or model/domain objects (DTO)
Also I...
- Use a Dependency Injection framework for repositories, this allows you to plug any database (StructureMap)
- Write unit tests and mock my repositories (NUnit)
However, if I had a new project, I would go code-first with EF4 instead of having a ORM-DTO mapping layer. (Code-First wit EF4)
Peace!
Another approach is to use plain-old-clr-objects (POCO). Your data abstraction and business layer can leverage this. Under the POCO domain model, typically you'd use a tool like nhibernate to manage persistance.
Rather than interfaces, nhibernate introduces a "proxy" to introduce persistence behaviour invisibly, through decoration (XML file or Attributes) . You can get quite productive with this approach once you get used to it.
Further, all three layers can leverage the same simple POCO objects which can simplify things somewhat.
re: different assemblies, either put the objects in a shareable assembly, or (like MS often do), use code generation to generate the same POCO "schema" in other layers. Sometimes an intermediate assembly is just not shareable... or you'd like to introduce variations in the additional layers (perhaps due to security concerns). So the link is to just depend on serialization, yet at the same time define once (the POCO schema) and introduce the schema to different layers through tooling (the code generation part).
Hope that helps.
精彩评论