Jason Butera
Jason Butera

Reputation: 2440

N-Tier Design for Common Business Tier but Different Presentation and Data Tiers

I have an application that exists in 3 different presentation tiers...web, mobile (offline) and desktop (offline). The core business objects are the same for all three, and they share the same validation and business rules. However, they all use different databases (web - SQL Server 2008, mobile/desktop - SQL Compact). Through a synchronization process, the desktop and mobile apps push and receive data from the server's SQL 2008 db.

I'm trying to come up with the best n-tier approach and I'm a little stuck. I've created an assembly for my business objects that encapsulates all of the business rules. I would very much like each object in this assembly to have a Save() method. However, I don't want this layer to be aware of any specific data layer. Basically, I want all three presentation layers to populate these objects and call the Save() method. But I want the implementation of the Save() method to be different depending on the calling application.

I initially created an interface called IDataAdapter and then a static property on each object for the IDataAdapter. Then the Save() method just checked if this was set, and then pass the business object to it's Save() method.

public interface IDataAdapter
{
    void Save(BusinessProxy proxy);
}

public class BusinessProxy
{
    public IDataAdapter myAdapter { get; set; }

    public bool Save()
    {
        if (myAdapter == null)
            throw new Exception();
        myAdapter.Save(this);
    }
}

Of course, this isn't ideal because the presentation layer would need to have a reference to the data tier in order to set the Adapter property. I would really love to have some sort of plugin system where I could just swap out the data.dll depending on the app platform.

Does anybody have any suggestions on how to implement this a little better?

Upvotes: 1

Views: 429

Answers (3)

k3b
k3b

Reputation: 14755

if you mean with "the best n-tier approach" that the different layers should not know each other and there is only one method that link the parts together you can create a global DataAdapter-registry based on Dictionary

where the BusinessProxy can ask for its IDataAdapter to be used.

    public interface IDataAdapter
    {
        void Save(BusinessProxy proxy);
    }

    public class BusinessProxy
    {
        public static DataAdapterRegistry Adapter = new DataAdapterRegistry();

        public bool Save()
        {
            Adapter.Save(this);
            return true;
        }
    }

    public class DataAdapterRegistry : IDataAdapter
    {
        private Dictionary<Type, IDataAdapter> registry 
                                    = new Dictionary<Type, IDataAdapter>();

        public void Register(Type type, IDataAdapter adapter)
        {
            registry[type] = adapter;
        }

        public void Save(BusinessProxy proxy)
        {
            IDataAdapter adapter;
                if (registry.TryGetValue(proxy.GetType(), out adapter))
                   adapter.Save(proxy);
                else
                   throw new NotSupportedException(proxy.GetType().FullName);       
        }
    }

    class Customer : BusinessProxy
    {
    }

    class Order : BusinessProxy
    {
    }

    class Program
    {
        static void Main(string[] args)
        {
            BusinessProxy.Adapter.Register(typeof(Customer), new CustomerAdapter());
            BusinessProxy.Adapter.Register(typeof(Order), new OrderAdapter());

        }
    }

you can use a "inversion of control container" framework like spring.net to do this with xml-configurtaion files instad of hardcoded-Compiletime Initialisation.

Upvotes: 1

bondehagen
bondehagen

Reputation: 900

You can use IoC (for exsample structuremap) to register the spesific implementations of IDataAdapter in the presentationlayer.

An other approach could be MEF, so you can swap the assemblies when ever you want.

Upvotes: 0

Tim Jarvis
Tim Jarvis

Reputation: 18815

I am a big fan of Simple.

One thing that you could do, is simply separate out your Save method to the platform dependant assembly. Just make it an extension method so that to your end user it looks like part of their IDataAdapter. Simple, clean.

Upvotes: 0

Related Questions