通用业务层的N层设计,但不同的表示和数据层

时间:2010-11-24 22:37:35

标签: c# n-tier-architecture

我有一个应用程序,存在于3个不同的表示层... web,移动(离线)和桌面(离线)。核心业务对象对于所有三个都是相同的,并且它们共享相同的验证和业务规则。但是,它们都使用不同的数据库(Web - SQL Server 2008,移动/桌面 - SQL Compact)。通过同步过程,桌面和移动应用程序从服务器的SQL 2008 db中推送和接收数据。

我正在努力想出最好的n级方法而且我有点卡住了。我为业务对象创建了一个程序集,它封装了所有业务规则。我非常希望这个程序集中的每个对象都有一个Save()方法。但是,我不希望此层知道任何特定的数据层。基本上,我希望所有三个表示层都填充这些对象并调用Save()方法。但我希望Save()方法的实现因调用应用程序而异。

我最初创建了一个名为IDataAdapter的接口,然后在IDataAdapter的每个对象上创建了一个静态属性。然后Save()方法刚检查是否已设置,然后将业务对象传递给它的Save()方法。

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);
    }
}

当然,这并不理想,因为表示层需要引用数据层才能设置Adapter属性。我真的很想有一些插件系统,我可以根据应用程序平台换掉data.dll。

有没有人对如何更好地实现这一点有任何建议?

3 个答案:

答案 0 :(得分:1)

如果你的意思是“最好的n层方法” 不同的层不应该彼此了解 并且只有一种方法将各部分链接在一起 您可以创建一个全局DataAdapter注册表 基于字典

BusinessProxy可以要求使用其IDataAdapter。

    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());

        }
    }

你可以使用像spring.net这样的“反转控制容器”框架,用xml-configurtaion文件实现硬编码 - 编译时初始化。

答案 1 :(得分:0)

我是Simple的粉丝。

您可以做的一件事就是将Save方法与平台相关的程序集分开。只需将其设为扩展方法,以便最终用户看起来像IDataAdapter的一部分。简单,干净。

答案 2 :(得分:0)

您可以使用IoC(例如structuremap)在表示层中注册IDataAdapter的特定实现。

另一种方法可能是MEF,因此您可以随时交换程序集。