在学习 mojoportal时,看到mojoportal调用editor使用了provider,顺便温习一下provider模式。
How to Write a Provider Model
原文地址: http://dotnetslackers.com/articles/designpatterns/HowToWriteAProviderModel.aspx)
这里只是简要的学习一下,做个笔记
自定义建立provider ,分四步
第一步: Main Data Provider Class
Main Data Provider Class 也是一个抽象类,定义了所有相关的数据操作方法。
这个抽象的数据操作方法类必须继承自System.Configuration.Provider.ProviderBase
基类
举例:
2using System.Collections.Generic;
3using System.Linq;
4using System.Text;
5using System.Configuration.Provider;
6
7namespace SampleProvider
8{
9 public abstract class DataProvider : ProviderBase
10 {
11 // Adds a text value for a specified ID to the storage
12 public abstract void AddText(int id, string text);
13
14 // Gets the text associated to a specified ID
15 public abstract string GetText(int id);
16 }
17}
正如你看到的,这个main provider class 继承自
ProviderBase抽象
类,定义了两个抽象方法,这两个方法需要被不同的provider 实现你应该明白,这个main provider class 是你的provider 中抽象的方法定义的地方。
第二步:Data Provider Collection
provider 集合类,继承自
System.Configuration.ProviderCollection
基类ProviderCollection
类暴露了几个方法处理配置文件中定义的provider类关键的一点是,providerCollection类返回main provider class 一个实例
代码如下:
2using System;
3using System.Collections.Generic;
4using System.Linq;
5using System.Text;
6using System.Configuration.Provider;
7
8namespace SampleProvider
9{
10 public class DataProviderCollection : ProviderCollection
11 {
12 // Return an instance of DataProvider
13 // for a specified provider name
14 new public DataProvider this[string name]
15 {
16 get { return (DataProvider)base[name]; }
17 }
18 }
19}
第三步:Data Provider Configuration
下一步工作是写一个 data provider configuration 类,用来读取配置文件
这个类需要引用
System.Configuration.ConfigSection命名空间.
在你的配置类中,你需要定义一个类型为System.Configuraiton.ProviderSettingsCollection的属性。
这个属性会从基类中返回一个实例。
这个类中,所有属性必须装饰 ConfigurationProperty
标签
1using System;
2using System.Collections.Generic;
3using System.Linq;
4using System.Text;
5using System.Configuration;
6
7namespace SampleProvider
8{
9 public class DataProviderConfiguration : ConfigurationSection
10 {
11 [ConfigurationProperty("providers")]
12 public ProviderSettingsCollection Providers
13 {
14 get
15 {
16 return (ProviderSettingsCollection)base["providers"];
17 }
18 }
19
20 [ConfigurationProperty("default", DefaultValue = "SqlProvider")]
21 public string Default
22 {
23 get
24 {
25 return (string)base["default"];
26 }
27 set
28 {
29 base["default"] = value;
30 }
31 }
32 }
33}
上面的代码中,定义了2个属性,第一个属性类型是ProviderSettingsCollection
,名称是Providers
它映射到配置文件的<providers
/>
元素
第二个方法设置了默认provider的名称,默认使用sqlProvider.
第四步:Data Provider Manager
这一步中你不需要继承接口或基类,只要根据你的需求来写。
data provider Manager的主要目的是初始化一个具体的 provider类,并在内存中加载配置信息。
初始化时,你需要为你的data provider获取配置信息,并在内存中建立一个具体的实例。
为了使代码工作,你的Data Provider Manager类中必须包含一个静态的public Initialize
方法
代码如下:
1using System;
2using System.Collections.Generic;
3using System.Linq;
4using System.Text;
5using System.Configuration;
6using System.Web.Configuration;
7
8namespace SampleProvider
9{
10 public class DataProviderManager
11 {
12 private static DataProvider defaultProvider;
13 private static DataProviderCollection providers;
14
15 static DataProviderManager()
16 {
17 Initialize();
18 }
19
20 private static void Initialize()
21 {
22 DataProviderConfiguration configuration =
23 (DataProviderConfiguration)
24 ConfigurationManager.GetSection("SampleProvider");
25
26 if (configuration == null)
27 throw new ConfigurationErrorsException
28 ("SampleProvider configuration section is not set correctly.");
29
30 providers = new DataProviderCollection();
31
32 ProvidersHelper.InstantiateProviders(configuration.Providers
33 , providers, typeof(DataProvider));
34
35 providers.SetReadOnly();
36
37 defaultProvider = providers[configuration.Default];
38
39 if (defaultProvider == null)
40 throw new Exception("defaultProvider");
41 }
42
43 public static DataProvider Provider
44 {
45 get
46 {
47 return defaultProvider;
48 }
49 }
50
51 public static DataProviderCollection Providers
52 {
53 get
54 {
55 return providers;
56 }
57 }
58 }
59}
Default Sql Data Provider
2using System.Collections.Generic;
3using System.Linq;
4using System.Text;
5using System.Data.SqlClient;
6using System.Configuration;
7using System.Collections.Specialized;
8
9namespace SampleProvider
10{
11 public class SqlDataProvider : DataProvider
12 {
13 private string _connectionString = string.Empty;
14
15 public override void Initialize(string name, NameValueCollection config)
16 {
17 base.Initialize(name, config);
18
19 this._connectionString = config["connectionString"];
20
21 if (string.IsNullOrEmpty(this._connectionString))
22 throw new ConfigurationErrorsException
23 ("connectionString must be set to the appropriate value");
24 }
25
26 public override void AddText(int id, string text)
27 {
28 using (SqlConnection connection = new SqlConnection(this._connectionString))
29 {
30 // For real world scnearios use parameterized SQL to avoid SQL injections!
31 string commandText = string.Format
32 ("INSERT INTO SampleTable (Id, Value) VALUES ({0}, '{1}')", id, text);
33 SqlCommand command = new SqlCommand(commandText, connection);
34 command.CommandType = System.Data.CommandType.Text;
35
36 connection.Open();
37 command.ExecuteNonQuery();
38 connection.Close();
39 command.Dispose();
40 }
41 }
42
43 public override string GetText(int id)
44 {
45 string result = string.Empty;
46
47 using (SqlConnection connection = new SqlConnection(this._connectionString))
48 {
49 string commandText = string.Format("SELECT Value FROM SampleTable WHERE Id = {0}", id);
50 SqlCommand command = new SqlCommand(commandText, connection);
51 command.CommandType = System.Data.CommandType.Text;
52
53 connection.Open();
54
55 result = command.ExecuteScalar() as string;
56
57 connection.Close();
58 command.Dispose();
59 }
60
61 return result;
62 }
63 }
64
添加配置文件
1:在<configSections> </configSections>中添加代码如下
<configSections>
<section name="SampleProvider"
type="SampleProvider.DataProviderConfiguration, SampleProvider" />
</configSections>
2<configuration
>
</configuration>中添加代码如下
<SampleProvider default="SqlProvider">
<providers>
<add name="SqlProvider"
type="SampleProvider.SqlDataProvider, SampleProvider"
connectionString="Data Source=.\SQLEXPRESS;AttachDbFilename=|DataDirectory|\DB.mdf;Integrated
curity=True;User Instance=True" />
</providers>
</SampleProvider>
测试代码如下:
2
3<%@ Import Namespace="SampleProvider" %>
4<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
5 "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
6<html xmlns="http://www.w3.org/1999/xhtml">
7
8<script runat="server" language="c#">
9 protected void btnAdd_Click(object sender, EventArgs e)
10 {
11 try
12 {
13 DataProviderManager.Provider.AddText
14 (Convert.ToInt32(txtId.Text), txtValue.Text);
15 lblResult.Text = "Data added successfully!";
16 }
17 catch (Exception ex)
18 {
19 lblResult.Text = ex.Message + "<br /> " + ex.StackTrace;
20 }
21 }
22
23 protected void btnSelect_Click(object sender, EventArgs e)
24 {
25 try
26 {
27 lblData.Text = DataProviderManager.Provider.GetText
28 (Convert.ToInt32(txtIdToSelect.Text));
29 }
30 catch (Exception ex)
31 {
32 lblData.Text = ex.Message + "<br /> " + ex.StackTrace;
33 }
34 }
35</script>
36
37<head runat="server">
38 <title>Untitled Page</title>
39</head>
40<body>
41 <form id="form1" runat="server">
42 <div>
43 <h1>
44 Add Data</h1>
45 Enter ID: <asp:TextBox ID="txtId" runat="server"></asp:TextBox><br />
46 Enter Value: <asp:TextBox ID="txtValue" runat="server"></asp:TextBox><br />
47 <asp:Button ID="btnAdd" runat="server" Text="Add" OnClick="btnAdd_Click" /><br />
48 <asp:Label ID="lblResult" runat="server" Text=""></asp:Label>
49 </div>
50 <div>
51 <h1>
52 Select Data</h1>
53 Enter ID: <asp:TextBox ID="txtIdToSelect" runat="server"></asp:TextBox><br />
54 <asp:Button ID="btnSelect" runat="server" Text="Select" OnClick="btnSelect_Click" /><br />
55 <asp:Label ID="lblData" runat="server" Text=""></asp:Label>
56 </div>
57 </form>
58</body>
59</html>