打造属于你的提供者(Provider = Strategy + Factory Method)

 

1.1.1 摘要

在日常系统设计中,我们也许听说过提供者模式,甚至几乎每天都在使用它,在.NET Framkework 2.0中微软提出了提供者模式(Provider),所以我们可以发现.NET Framkework中有很多类命名都含有“Provider”,例如:IFormatProvider,RSACryptoServiceProvider等等,由此可见它们都间接或直接使用了提供者模式这一设计思想,现在让我们来介绍一下提供者模式(Provider)。

1.1.2 正文

首先让我们通过提供者模式(Provider)结构图,了解什么是提供者模式(Provider)。

图1提供者模式(Provider)结构图

通过上面的结构图我们发现提供者模式(Provider),并没有想象中的那么复杂而且整个结构就是使用了一些继承关系而已。

提供者模式(Provider)的结构图,和我们熟悉的策略模式(Strategy)结构基本一致就是通过继承扩展不同种类的算法。

策略模式(Strategy):它定义了算法家族,分别封装起来,让它们之间可以互相替换,此模式让算法的变化,不会影响到使用算法的客户。

图2策略模式(Strategy)结构图

所以很多人都喜欢把提供者模式(Provider)和策略模式(Strategy)进行对比,更甚至有些人认为就是策略模式(Strategy),其实不然我们可以发现每种提供者它们都是继承于一个基类ProviderBase,无论是系统还是自定义的提供者都必须继承于它。

现在让我们看看抽象类ProviderBase。

public abstract class ProviderBase
{
    // Fields
    private string _Description;
    private bool _Initialized;
    private string _name;

    // Methods
    protected ProviderBase();
    public virtual void Initialize(string name, NameValueCollection config);

    // Properties
    public virtual string Description { get; }
    public virtual string Name { get; }
}

通过上面的代码我们发现,ProviderBase只包含一些描述字段和属性,还有就是一个无参构造函数和一个初始化方法Initialize(string name, NameValueCollection config)。该方法是提供者模式实现动态调用的核心方法(DI的实现)。

在ProviderBase中提供了Initialize方法实现和统一签名,然后让提供者重写该方法,现在我们又有问题了究竟这个方法要实现什么功能呢?让我们看看Initialize方法的实现吧!

public virtual void Initialize(string name, NameValueCollection config)
{
    lock (this)
    {
        if (this._Initialized)
        {
            throw new InvalidOperationException(
                SR.GetString("Provider_Already_Initialized"));
        }
        this._Initialized = true;
    }
    if (name == null)
    {
        throw new ArgumentNullException("name");
    }
    if (name.Length == 0)
    {
        throw new ArgumentException(
            SR.GetString("Config_provider_name_null_or_empty"), "name");
    }
    this._name = name;
    if (config != null)
    {
        this._Description = config["description"];
        config.Remove("description");
    }
}

其实这个方法功能很简单就是去读我们配置文件相应节点的值, 现在我们知道可以通过重新 Initialize 方法,可以实现从配置文件中读取 Provider 的信息(如:name,type,connectionString 等)。我们都知道继承使得类之间的耦合度增加, 这就是策略模式的一个缺点具体算法通过继承来进行扩展。但我们看到提供者模式(Provider)使用了一种比较灵活方法对具体提供者进行扩展。

图 3 ASP.NET中的提供者模式(Provider)

通过上图我们发现.NET中的MembershipProvider,RoleProvider,SiteMapProvider等提供者都必须继承于ProviderBase类,接着是具体实现提供者的类。除此之外,我们自定义提供者都必须继承于ProviderBase类。

我们对于提供者模式(Provider)有了初步的认识,那么现在让我们定义属于自己的提供者吧!

假设我们要设计数据库提供者,考虑到我们系统的灵活性和扩展性,我们应该使系统可以在不同数据之间无缝切换,由于数据库的种类有:SqlServer,Oracle,MySql,SQLite等,首先定义一个抽象类DataProvider让具体数据提供者来实现它。

图 4 DataProvider的设计

我们定义一个DataProvider类继承于ProviderBase,然后添加数据连接字符串,存储过程名字和参数属性,最后就是一系列的对数据库操作方法。

/// <summary>
/// Defines the methods that Data providers should be implemented.
/// </summary>
public abstract class DataProvider : ProviderBase
{

    /// <summary>
    /// Runs the specified transaction.
    /// </summary>
    /// <param name="transaction">The transaction.</param>
    public abstract void Run(DbTransaction transaction);

    /// <summary>
    /// Runs the specified transaction.
    /// </summary>
    /// <param name="transaction">The transaction.</param>
    /// <param name="parameters">The stored procedure  parameters.</param>
    public abstract void Run(DbTransaction transaction, DbParameter[] parameters);

    //public abstract DbDataReader Run(DbParameter[] parameters);

    /// <summary>
    /// Runs the specified connection string.
    /// </summary>
    /// <param name="connectionString">The connection string.</param>
    /// <param name="parameters">The stored procedure  parameters.</param>
    /// <returns>Returns dataset.</returns>
    public abstract DataSet Run(string connectionString, DbParameter[] parameters);

    /// <summary>
    /// Runs the scalar.
    /// </summary>
    /// <param name="connectionString">The connection string.</param>
    /// <param name="parameters">The stored procedure  parameters.</param>
    /// <returns>Returns an object.</returns>
    public abstract object RunScalar(string connectionString, DbParameter[] parameters);

    /// <summary>
    /// Runs the scalar.
    /// </summary>
    /// <param name="transaction">The transaction.</param>
    /// <param name="parameters">The stored procedure  parameters.</param>
    /// <returns></returns>
    public abstract object RunScalar(SqlTransaction transaction, DbParameter[] parameters);

    /// <summary>
    /// Runs the specified connectionstring.
    /// </summary>
    /// <param name="connectionstring">The connectionstring.</param>
    /// <returns></returns>
    public abstract DataSet Run(string connectionstring);

    /// <summary>
    /// Runs this instance.
    /// </summary>
    public abstract void Run();

    /// <summary>
    /// Runs the specified parameters.
    /// </summary>
    /// <param name="parameters">The stored procedure  parameters.</param>
    /// <returns></returns>
    public abstract DataSet Run(DbParameter[] parameters);

    /// <summary>
    /// Runs the specified command type.
    /// </summary>
    /// <param name="commandType">Type of the command.</param>
    /// <param name="commandText">The command text stored procedure or sql queries.</param>
    /// <returns></returns>
    public abstract DbDataReader Run(CommandType commandType, string commandText);

    /// <summary>
    /// Gets or sets the stored procedure parameters.
    /// </summary>
    /// <value>
    /// The stored procedure parameters.
    /// </value>
    public DbParameter[] Parameters { get; set; }

    /// <summary>
    /// Gets or sets the name of the stored procedure.
    /// </summary>
    /// <value>
    /// The name of the stored procedure.
    /// </value>
    public string StoredProcedureName { get; set; }

    /// <summary>
    /// Gets the default connection string from webconfig file.
    /// </summary>
    protected string ConnectionString
    {
        get { return ConfigurationManager.ConnectionStrings["SQLCONN"].ToString(); }
    }
}

上面我们完成了抽象的提供者,这里仅仅是一些抽象的方法并没有具体的实现,所以我们要通过具体的提供者来实现这些抽象的方法。接下来让我们定义具体的提供者SqlDataProvider和OracleDataProvider。

图 5具体提供者设计

/// <summary>
/// The implementor of DataProvder.
/// </summary>
public class SqlDataProvider : DataProvider
{

    #region Fields

    private string _connection = string.Empty;

    #endregion

    /// <summary>
    /// Default parameterless constructor used by Reflection.
    /// </summary>
    public SqlDataProvider()
    {
        // Just used by Reflection.
    }

    /// <summary>
    /// Initializes the provider.
    /// </summary>
    /// <param name="name">The name of provider, setting in webconfig file.</param>
    /// <param name="config">The value collection of config.</param>
    public override void Initialize(string name, NameValueCollection config)
    {
        // Due to ProviderBase has check name and config are available or not,
        // So no need validate name and config.
        base.Initialize(name, config);
        _connection = config["connectionString"];

        if (string.IsNullOrEmpty(_connection))
            throw new ConfigurationErrorsException("Connection string can't empty.");
    }

    /// <summary>
    /// Runs the specified transaction.
    /// </summary>
    /// <param name="transaction">The transaction.</param>
    public override void Run(DbTransaction transaction)
    {
        SqlHelper.ExecuteNonQuery(transaction as SqlTransaction,
            CommandType.StoredProcedure, StoredProcedureName, Parameters);
    }

    /// <summary>
    /// Runs the specified transaction.
    /// </summary>
    /// <param name="transaction">The transaction.</param>
    /// <param name="parameters">The parameters.</param>
    public override void Run(DbTransaction transaction, DbParameter[] parameters)
    {
        SqlHelper.ExecuteNonQuery(transaction as SqlTransaction,
            CommandType.StoredProcedure, StoredProcedureName, parameters as SqlParameter[]);
    }

    /// <summary>
    /// Runs the specified connection string.
    /// </summary>
    /// <param name="connectionString">The connection string.</param>
    /// <param name="parameters">The parameters.</param>
    /// <returns></returns>
    public override DataSet Run(string connectionString, DbParameter[] parameters)
    {
        DataSet ds = SqlHelper.ExecuteDataset(connectionString, StoredProcedureName, parameters);
        return ds;
    }

    /// <summary>
    /// Runs the specified parameters.
    /// </summary>
    /// <param name="parameters">The stored procedure  parameters.</param>
    /// <returns></returns>
    public override DataSet Run(DbParameter[] parameters)
    {
        DataSet ds = SqlHelper.ExecuteDataset(ConnectionString, StoredProcedureName, parameters);

        return ds;

    }

    /// <summary>
    /// Runs the scalar.
    /// </summary>
    /// <param name="connectionString">The connection string.</param>
    /// <param name="parameters">The parameters.</param>
    /// <returns></returns>
    public override object RunScalar(string connectionString, DbParameter[] parameters)
    {
        object obj = SqlHelper.ExecuteScalar(connectionString, StoredProcedureName, parameters);

        return obj;
    }

    /// <summary>
    /// Runs the scalar.
    /// </summary>
    /// <param name="transaction">The transaction.</param>
    /// <param name="parameters">The parameters.</param>
    /// <returns></returns>
    public override object RunScalar(SqlTransaction transaction, DbParameter[] parameters)
    {
        object obj = SqlHelper.ExecuteScalar(transaction, StoredProcedureName, parameters);

        return obj;
    }

    /// <summary>
    /// Runs the specified connectionstring.
    /// </summary>
    /// <param name="connectionstring">The connectionstring.</param>
    /// <returns></returns>
    public override DataSet Run(string connectionstring)
    {
        DataSet ds = SqlHelper.ExecuteDataset(connectionstring,
            CommandType.StoredProcedure, StoredProcedureName);

        return ds;

    }

    /// <summary>
    /// Runs this instance.
    /// </summary>
    public override void Run()
    {
        SqlHelper.ExecuteNonQuery(ConnectionString,
            CommandType.StoredProcedure, StoredProcedureName, Parameters);
    }

    /// <summary>
    /// Runs the specified parameters.
    /// </summary>
    /// <param name="commandType">Type of the command.</param>
    /// <param name="commandText">The command text stored procedure or sql queries.</param>
    /// <returns></returns>
    public override DbDataReader Run(CommandType commandType, string commandText)
    {
        SqlDataReader dr = SqlHelper.ExecuteReader(ConnectionString, CommandType.Text, commandText);

        return dr;

    }

    public SqlParameter[] Parameters { get; set; }

}

我们很快就完成了SqlDataProvider类,这是由于我们把具体的实现都放在了SqlHelper中。在SqlHelper中包含具体的数据库操作方法,在其中包含了一些烦琐的数据库操作方法,如果我们说要让大家自己去完成这个Helper类,那么肯定是一个很痛苦的过程,而且严重影响了开发的效率,考虑到数据库操作方法的可重用性微软已经给我们提供了对SqlServer操作的Helper类(包含C#和VB)。

现在SqlDataProvider类基本完成了,接着我们创建一个DataProviderManager类,在它里面提供工厂方法用来创建提供者对象。

图 6 DataProviderManager设计

在DataProviderManager类中的CreateProvider方法负责创建提供者对象(如:SqlDataProvider和OracleDataProvider)。

/// <summary>
/// The factory method to creates the provider instance.
/// </summary>
/// <returns>The instances of provider.</returns>
public static object CreateProvider()
{
    LoadProviders();

    return _provider;
}

/// <summary>
/// Loads the providers by webconfig setting.
/// </summary>
private static void LoadProviders()
{
    // providers are loaded just once
    if (null == _providers)
    {
        // Synchronize the process of loading the providers
        lock (SyncLock)
        {
            // Double confirm that the _provider is still null.
            if (null == _provider)
            {
                try
                {
                    // Reads the webconfig file corresponding node.
                    DataProviderSection section = (DataProviderSection)
                                                  WebConfigurationManager.GetSection(
                                                  "system.web/dataProviderService");

                    _providers = new DataProviderCollection();

                    // Creates provider instance, and invokes ProviderBase's Initialize function.
                    ProvidersHelper.InstantiateProviders(section.Providers, Providers, typeof(DataProvider));

                    // Gets the default in the collection.
                    _provider = Providers[section.DefaultProvider];
                }
                catch
                {
                    throw new ProviderException("Can't create instance");
                }
            }
        }
    }
}

通过上面的代码我们hard code获取提供者信息的配置文件节点,那么DataProviderManager类根据配置文件设置来实例化提供者对象,接下来让我们设置配置文件。

图 7 提供者模式配置文件设置

首先我们在configSections中,设置自定义数据库提供者名称(dataProviderService)和命名空间,接着我们在web节点中配置dataProviderService,在其中我们配置了默认的数据库提供者为SqlDataProvider,接着我们再设置其它数据库提供者OracleDataProvider。

现在我们已经完成了自定义数据库提供者了,那么接下来让我们通过一个简单的web界面程序来测试一下吧!

图 8 界面效果图

由于时间的关系我们已经把界面设计好了,现在让我们测试一下数据库提供者。

图 9 测试效果图

/// <summary>
/// Insert data into to database.
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
protected void btnAdd_Click(object sender, EventArgs e)
{
    try
    {
        if (!String.IsNullOrEmpty(this.txtUserName.Text.Trim()))
        {
            UserInfoParameters userInfo = new UserInfoParameters(this.txtUserName.Text.Trim());
            DataProvider provider = DataProviderManager.CreateProvider() as DataProvider;
            provider.StoredProcedureName = "sp_AddUsertt";
            provider.Run(userInfo.Parameters);
            this.lblMsg.Text = "Save successful.";
        }

    }
    catch (Exception ex)
    {
        this.lblMsg.Text = "Save failed.";
        throw ex;
    }
}

上面我们调用SqlDataProvider把用户名写入到数据库。

    /// <summary>
    /// Get id from database.
    /// </summary>
    /// <param name="sender"></param>
    /// <param name="e"></param>
    protected void btnSelect_Click(object sender, EventArgs e)
    {
        try
        {
            if (!String.IsNullOrEmpty(this.txtUserName.Text.Trim()))
            {

                UserInfoParameters userInfo = new UserInfoParameters(this.txtUserName.Text);

                DataProvider provider = DataProviderManager.CreateProvider() as DataProvider;

                string strSql = String.Format(
                    "SELECT UserID FROM UserInfo WHERE UserName = '{0}'", this.txtUserName.Text);
                SqlDataReader dr = provider.Run(CommandType.Text, strSql) as SqlDataReader;
                while (dr.Read())
                {
                    this.lblMsg.Text = "The user id is: " + dr[0].ToString();
                }
            }

        }

        catch (Exception ex)
        {
            this.lblMsg.Text = "This id not existed";
            throw ex;
        }
    }
}

接着我们根据用户名从数据库中读取用户id。

/// <summary>
/// Sets stored procedure parameters.
/// </summary>
public class UserInfoParameters
{

    private string _userName;

    public UserInfoParameters(string userName)
    {
        _userName = userName;
        Build();
    }

    private void Build()
    {
        SqlParameter[] sqlParameters = { new SqlParameter("@UserName", _userName) };
        Parameters = sqlParameters;
    }

    public SqlParameter[] Parameters { get; set; }
}

我们通过SqlDataProvider提供者成功把User Name写入数据库中,而且在数据库中生成的id为11。

1.1.3 总结

通过本文的介绍相信大家对提供者模式(Provider)有了初步的了解,在我看来提供者模式不仅仅是包含策略模式(Strategy)思想,而且它通过工厂方法(Factory Method)更好地改善了继承使得耦合度增加的缺点,所以说提供者包含了策略模式(Strategy)和工厂方法(Factory Method)设计思想。

我们知道所有提供者模式(Provider)必须继承于抽象基类ProviderBase,然后我们就可以定义各种各样的提供者。

希望通过阅读本文后大家对于提供者模式有更深的了解。

提供者模式参考资料

Provider Model Design Pattern and Specification, Part 1

The ASP.NET 2.0 Provider Model.

Designing loosely coupled components in .NET  Provider Pattern

Demo下载

 
 
 
 

设计模式 - Provider Pattern(提供者模式)

2010年11月16日 09:36:00 ztmaster 阅读数:4620
 

介绍
为一个API进行定义和实现的分离。

示例
有一个Message实体类,对它的操作有Insert()和Get()方法,持久化数据在SqlServer数据库中或Xml文件里。根据配置文件中的配置来决定数据持久化方案是使用SqlServer数据库还是Xml文件。

MessageModel

using System;

namespace Pattern.Provider
{
    /// <summary>
    /// Message实体类
    /// </summary>
    public class MessageModel
    {
        /// <summary>
        /// 构造函数
        /// </summary>
        /// <param name="msg">Message内容</param>
        /// <param name="pt">Message发布时间</param>
        public MessageModel(string msg, DateTime pt)
        {
            this._message = msg;
            this._publishTime = pt;
        }

        private string _message;
        /// <summary>
        /// Message内容
        /// </summary>
        public string Message
        {
            get { return _message; }
            set { _message = value; }
        }

        private DateTime _publishTime;
        /// <summary>
        /// Message发布时间
        /// </summary>
        public DateTime PublishTime
        {
            get { return _publishTime; }
            set { _publishTime = value; }
        }
    }
}

MessageProvider

using System.Configuration.Provider;
using System.Collections.Generic;

namespace Pattern.Provider
{
    /// <summary>
    /// 操作Message抽象类
    /// </summary>
    public abstract class MessageProvider : ProviderBase
    {
        /// <summary>
        /// 插入Message
        /// </summary>
        /// <param name="mm">Message实体对象</param>
        /// <returns></returns>
        public abstract bool Insert(MessageModel mm);

        /// <summary>
        /// 获得Message
        /// </summary>
        /// <returns></returns>
        public abstract List<MessageModel> Get();
    }
}

SqlMessageProvider

using System;
using System.Collections.Specialized;
using System.Collections.Generic;

using System.Configuration.Provider;
using System.Configuration;

namespace Pattern.Provider
{
    /// <summary>
    /// Sql方式操作Message
    /// </summary>
    public class SqlMessageProvider : MessageProvider
    {
        private string _connectionString;

        /// <summary>
        /// 插入Message
        /// </summary>
        /// <param name="mm">Message实体对象</param>
        /// <returns></returns>
        public override bool Insert(MessageModel mm)
        {
            // 代码略
            return true;
        }

        /// <summary>
        /// 获取Message
        /// </summary>
        /// <returns></returns>
        public override List<MessageModel> Get()
        {
            List<MessageModel> l = new List<MessageModel>();
            l.Add(new MessageModel("SQL方式,连接字符串是" + this._connectionString, DateTime.Now));

            return l;
        }

        /// <summary>
        /// 初始化提供程序。
        /// </summary>
        /// <param name="name">该提供程序的友好名称。</param>
        /// <param name="config">名称/值对的集合,表示在配置中为该提供程序指定的、提供程序特定的属性。</param>
        public override void Initialize(string name, NameValueCollection config)
        {
            if (string.IsNullOrEmpty(name))
                name = "MessageProvider";

            if (null == config)
                throw new ArgumentException("config参数不能为null");

            if (string.IsNullOrEmpty(config["description"]))
            {
                config.Remove("description");
                config.Add("description", "SqlServer操作Message");
            }

            base.Initialize(name, config);

            string temp = config["connectionStringName"];
            if (temp == null || temp.Length < 1)
                throw new ProviderException("connectionStringName属性缺少或为空");

            _connectionString = ConfigurationManager.ConnectionStrings[temp].ConnectionString;
            if (_connectionString == null || _connectionString.Length < 1)
            {
                throw new ProviderException("没找到'" + temp + "'所指的连接字符串,或所指连接字符串为空");
            }

            config.Remove("connectionStringName");
        }
    }
}

XmlMessageProvider

using System;
using System.Collections.Specialized;
using System.Collections.Generic;

using System.Configuration.Provider;
using System.Configuration;

namespace Pattern.Provider
{
    /// <summary>
    /// Xmll方式操作Message
    /// </summary>
    public class XmlMessageProvider : MessageProvider
    {
        private string _connectionString;

        /// <summary>
        /// 插入Message
        /// </summary>
        /// <param name="mm">Message实体对象</param>
        /// <returns></returns>
        public override bool Insert(MessageModel mm)
        {
            // 代码略
            return true;
        }

        /// <summary>
        /// 获取Message
        /// </summary>
        /// <returns></returns>
        public override List<MessageModel> Get()
        {
            List<MessageModel> l = new List<MessageModel>();
            l.Add(new MessageModel("XML方式,连接字符串是" + this._connectionString, DateTime.Now));

            return l;
        }

        /// <summary>
        /// 初始化提供程序。
        /// </summary>
        /// <param name="name">该提供程序的友好名称。</param>
        /// <param name="config">名称/值对的集合,表示在配置中为该提供程序指定的、提供程序特定的属性。</param>
        public override void Initialize(string name, NameValueCollection config)
        {
            if (string.IsNullOrEmpty(name))
                name = "MessageProvider";

            if (null == config)
                throw new ArgumentException("config参数不能为null");

            if (string.IsNullOrEmpty(config["description"]))
            {
                config.Remove("description");
                config.Add("description", "XML操作Message");
            }

            base.Initialize(name, config);

            string temp = config["connectionStringName"];
            if (temp == null || temp.Length < 1)
                throw new ProviderException("connectionStringName属性缺少或为空");

            _connectionString = ConfigurationManager.ConnectionStrings[temp].ConnectionString;
            if (_connectionString == null || _connectionString.Length < 1)
            {
                throw new ProviderException("没找到'" + temp + "'所指的连接字符串,或所指连接字符串为空");
            }

            config.Remove("connectionStringName");
        }
    }
}

MessageProviderCollection

using System.Configuration.Provider;
using System;

namespace Pattern.Provider
{
    /// <summary>
    /// Message的Provider集合类
    /// </summary>
    public class MessageProviderCollection : ProviderCollection
    {
        /// <summary>
        /// 向集合中添加提供程序。
        /// </summary>
        /// <param name="provider">要添加的提供程序。</param>
        public override void Add(ProviderBase provider)
        {
            if (provider == null)
                throw new ArgumentNullException("provider参数不能为null");

            if (!(provider is MessageProvider))
                throw new ArgumentException("provider参数类型必须是MessageProvider.");

            base.Add(provider);
        }
    }
}

MessageProviderConfigurationSection

using System.Configuration;

namespace Pattern.Provider
{
    /// <summary>
    /// Message的Provider的配置
    /// </summary>
    public class MessageProviderConfigurationSection : ConfigurationSection
    {
        private readonly ConfigurationProperty _defaultProvider;
        private readonly ConfigurationProperty _providers;
        private ConfigurationPropertyCollection _properties;
        
        /// <summary>
        /// 构造函数
        /// </summary>
        public MessageProviderConfigurationSection()
        {
            _defaultProvider = new ConfigurationProperty("defaultProvider", typeof(string), null);
            _providers = new ConfigurationProperty("providers", typeof(ProviderSettingsCollection), null);
            _properties = new ConfigurationPropertyCollection();

            _properties.Add(_providers);
            _properties.Add(_defaultProvider);
        }

        /// <summary>
        /// Message的默认的Provider
        /// </summary>
        [ConfigurationProperty("defaultProvider")]
        public string DefaultProvider
        {
            get { return (string)base[_defaultProvider]; }
            set { base[_defaultProvider] = value; }
        }

        /// <summary>
        /// Message的所有的Provider集合
        /// </summary>
        [ConfigurationProperty("providers", DefaultValue = "SqlMessageProvider")]
        [StringValidator(MinLength = 1)]
        public ProviderSettingsCollection Providers
        {
            get { return (ProviderSettingsCollection)base[_providers]; }
        }

        /// <summary>
        /// Message的Provider的属性集合
        /// </summary>
        protected override ConfigurationPropertyCollection Properties
        {
            get { return _properties; }
        }
    }
}

Message

using System;
using System.Collections.Generic;
using System.Configuration;
using System.Web.Configuration;

namespace Pattern.Provider
{
    /// <summary>
    /// 暴露给客户端用的Message的类(Context)
    /// </summary>
    public class Message
    {
        private static bool m_isInitialized = false;
        private static MessageProviderCollection _providers = null;
        private static MessageProvider _provider = null;

        /// <summary>
        /// 静态构造函数,初始化
        /// </summary>
        static Message()
        {
            Initialize();
        }

        /// <summary>
        /// 插入信息
        /// </summary>
        /// <param name="mm">Message实体对象</param>
        /// <returns></returns>
        public static bool Insert(MessageModel mm)
        {
            return _provider.Insert(mm);
        }

        /// <summary>
        /// 获取信息
        /// </summary>
        /// <returns></returns>
        public static List<MessageModel> Get()
        {
            return _provider.Get();
        }

        private static void Initialize()
        {
            try
            {
                MessageProviderConfigurationSection messageConfig = null;

                if (!m_isInitialized)
                {

                    // 找到配置文件中“MessageProvider”节点
                    messageConfig = (MessageProviderConfigurationSection)ConfigurationManager.GetSection("MessageProvider");

                    if (messageConfig == null)
                        throw new ConfigurationErrorsException("在配置文件中没找到“MessageProvider”节点");

                    _providers = new MessageProviderCollection();

                    // 使用System.Web.Configuration.ProvidersHelper类调用每个Provider的Initialize()方法
                    ProvidersHelper.InstantiateProviders(messageConfig.Providers, _providers, typeof(MessageProvider));

                    // 所用的Provider为配置中默认的Provider
                    _provider = _providers[messageConfig.DefaultProvider] as MessageProvider;

                    m_isInitialized = true;

                }
            }
            catch (Exception ex)
            {
                string msg = ex.Message;
                throw new Exception(msg);
            }
        }

        private static MessageProvider Provider
        {
            get
            {
                return _provider;
            }
        }

        private static MessageProviderCollection Providers
        {
            get
            {
                return _providers;
            }
        }
    }
}

Web.config

<?xml version="1.0" encoding="utf-8"?>
<configuration>
  <configSections>
    <section name="MessageProvider" type="Pattern.Provider.MessageProviderConfigurationSection, Pattern.Provider" />
  </configSections>
  <MessageProvider defaultProvider="SqlMessageProvider">
    <providers>
      <add name="XmlMessageProvider" type="Pattern.Provider.XmlMessageProvider, Pattern.Provider" connectionStringName="XmlConnection" />
      <add name="SqlMessageProvider" type="Pattern.Provider.SqlMessageProvider, Pattern.Provider" connectionStringName="SqlConnection" />
    </providers>
  </MessageProvider>
  <connectionStrings>
    <add name="SqlConnection" connectionString="server=.;database=db;uid=sa;pwd=sa" />
    <add name="XmlConnection" connectionString="XmlPath" />
  </connectionStrings>
</configuration>

Test

using System;
using System.Data;
using System.Configuration;
using System.Collections;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Web.UI.HtmlControls;

using Pattern.Provider;

public partial class Provider : System.Web.UI.Page
{
    protected void Page_Load(object sender, EventArgs e)
    {
        Response.Write(Message.Insert(new MessageModel("插入", DateTime.Now)));
        Response.Write("<br />");
        Response.Write(Message.Get()[0].Message + " " + Message.Get()[0].PublishTime.ToString());
    }
}

运行结果
True
SQL方式,连接字符串是server=.;database=db;uid=sa;pwd=sa 2007-1-22 8:21:44

OK
[源码下载]

最新文章

  1. js中对象使用
  2. C# 非UI线程对控件的控制
  3. HDU 5113 Black And White 回溯+剪枝
  4. 连接ssql语句
  5. 爬虫再探实战(四)———爬取动态加载页面——请求json
  6. LSP“浏览器劫持概念
  7. Cygwin下设置ls显示颜色
  8. Struts2中的ActionContext
  9. HTML——CSS样式表&amp;布局页面
  10. eclipse在Ubuntu 13.04下的安装过程
  11. AngularJs ng-repeat指令中怎么实现含有自定义指令的动态html
  12. 10分钟搞懂Tensorflow 逻辑回归实现手写识别
  13. Geometric regularity criterion for NSE: the cross product of velocity and vorticity 3: $u\times \f{\om}{|\om|}\cdot \f{\vLm^\be u}{|\vLm^\be u|}$
  14. [转帖]TLS 1.3 VS TLS 1.2,让你明白 TLS 1.3 的强大
  15. SSM框架的配置
  16. package.json版本号
  17. sun.misc.BASE64Encoder等类报错的解决方法
  18. L256 翻译
  19. iOS 网络操作与AFNetworking
  20. java日常知识点积累

热门文章

  1. JS的ES7支持
  2. [PHP] PHP汉字转拼音的方法
  3. 洛谷P1531 I Hate It题解
  4. (近万字)一篇文章带你了解HTML5和CSS3开发基础与应用-适合前端面试必备
  5. c语言之函数指针应用
  6. ASP.NET之MVC 微信公众号授权给第三方平台的技术实现流程(获取第三方平台access_token)
  7. 【2019年05月16日】A股最便宜的股票
  8. Nginx配置反向代理支持WebSocket
  9. java 获取类路径
  10. 关于深度学习框架 TensorFlow、Theano 和 Keras