.NET人字拖
万丈高楼平地起,我正在努力筑地基...
随笔- 133  文章- 0  评论- 606 
博客园  社区  首页  新随笔  联系  管理  订阅 订阅

[CommunityServer]自定义扩展Provider的实现.

  自定义扩展Provider当然要有自己的配制文件,在上一编文章中我们介绍了文件CommunityServer.config,在CORE节点我们可找到<provider>节点,这个配制,今天我们来看看从读取到实现的整个过程.当然我们的程序可能只有个别Provider需要扩展就不需要自己配制一个文件,我们可以通过在Web.config文件中配制一个节点用来存储Provider或直接放在<appSettings>中.

  下面我们来看看provider的配制文件:
 
PROVIDER
  1            <providers>
  2
  3                <clear/>
  4                <!--
  5                    SqlForumsProvider :
  6                        Microsoft(r)'s SQL Server Data Provider Configuration Section
  7
  8                        To configure manually, replace the value for connectionString with
  9                        your MSSQLSERVER's connect information.  
 10
 11                            For example, replace:
 12                                connectionString = "-SqlConnectiongString-" 
 13                            with:
 14                                connectionString = "server=127.0.0.1;database=CommunityServer;uid=Username;pwd=Password"
 15
 16
 17                        If installing into a shared web hosting company's database, you will most likely be installing from a
 18                        non-DBO (DataBase Owner) account.  To ensure your database objects can be accessed properly from the forums,
 19                        you may need to change the databaseOwner value below to your username/accoutname you have with your hosting company.
 20
 21                            For example, replace:
 22                                databaseOwner = "dbo"
 23                            with:
 24                                databaseOwner = "Username"
 25                -->
 26                <add 
 27                    name = "CommonDataProvider" 
 28                    type = "CommunityServer.Data.SqlCommonDataProvider, CommunityServer.SqlDataProvider" 
 29                    connectionStringName = "SiteSqlServer"    databaseOwnerStringName = "SiteSqlServerOwner"
 30                />
 31                
 32                <add 
 33                    name = "ForumDataProvider" 
 34                    type = "CommunityServer.Data.ForumsSqlDataProvider, CommunityServer.SqlDataProvider" 
 35                    connectionStringName = "SiteSqlServer"    databaseOwnerStringName = "SiteSqlServerOwner"
 36                />                
 37                
 38                <add 
 39                    name = "WeblogDataProvider" 
 40                    type = "CommunityServer.Data.WeblogSqlDataProvider, CommunityServer.SqlDataProvider" 
 41                    connectionStringName = "SiteSqlServer" databaseOwnerStringName = "SiteSqlServerOwner"
 42                />                
 43
 44                <add 
 45                    name = "GalleryDataProvider" 
 46                    type = "CommunityServer.Data.GallerySqlDataProvider, CommunityServer.SqlDataProvider" 
 47                    connectionStringName = "SiteSqlServer" databaseOwnerStringName = "SiteSqlServerOwner"                
 48                />
 49                
 50                <add 
 51                    name = "ProviderHelper" 
 52                    type = "CommunityServer.Data.WebSqlProviderHelper, CommunityServer.SqlDataProvider" 
 53                    connectionStringName = "SiteSqlServer" databaseOwnerStringName = "SiteSqlServerOwner"
 54                />
 55                
 56                <add 
 57                    name = "SiteUrlsDataProvider" 
 58                    type = "CommunityServer.Components.SiteUrlsData, CommunityServer.Components" 
 59                    path = "SiteUrls.config" 
 60                />
 61                
 62                <add 
 63                    name = "ApplicationKeyProvider"
 64                    type = "CommunityServer.Components.ApplicationKeyProvider, CommunityServer.Components" 
 65                />
 66                
 67                <add 
 68                    name = "EmailTemplateProvider"
 69                    type = "CommunityServer.Components.XmlEmailTemplateProvider, CommunityServer.Components" 
 70                />
 71
 72                <add 
 73                    name = "EmailQueueProvider"
 74                    type = "CommunityServer.Components.SqlEmailQueueProvider, CommunityServer.Components" 
 75                    connectionStringName = "SiteSqlServer" databaseOwnerStringName = "SiteSqlServerOwner"
 76                />
 77                
 78                <add 
 79                    name = "CSMDataProvider" 
 80                    type = "CommunityServer.Mail.Data.CSMSqlDataProvider, CommunityServer.Mail.Data.SqlDataProvider" 
 81                    connectionStringName = "SiteSqlServer" databaseOwnerStringName = "SiteSqlServerOwner"                
 82                />
 83                
 84                <add 
 85                    name =     "SearchProvider" 
 86                    type = "CommunityServer.Components.SearchBarrel.SearchBarrelProvider, CommunityServer.Components.SearchBarrel" />
 87
 88                <add 
 89                    name = "FileGalleryDataProvider" 
 90                    type = "CommunityServer.Data.FileGallerySqlDataProvider, CommunityServer.SqlDataProvider" 
 91                    connectionStringName = "SiteSqlServer" databaseOwnerStringName = "SiteSqlServerOwner"                
 92                />
 93                
 94                <add 
 95                    name = "FeedReaderDataProvider" 
 96                    type = "CommunityServer.Data.FeedReaderSqlDataProvider, CommunityServer.SqlDataProvider" 
 97                    connectionStringName = "SiteSqlServer" databaseOwnerStringName = "SiteSqlServerOwner"                
 98                />
 99
100                <add 
101                    name = "RollerBlogsDataProvider" 
102                    type = "CommunityServer.RollerBlogs.Data.RollerBlogsSqlDataProvider, CommunityServer.RollerBlogs" 
103                    connectionStringName = "SiteSqlServer" databaseOwnerStringName = "SiteSqlServerOwner"                
104                />
105
106                <add 
107                    name = "MemberRoleProfileProvider"
108                    type = "CommunityServer.MemberRole.CSMemberRoleProfileProvider, CommunityServer.MemberRole"
109                />
110                
111                
112            </providers>

  从上面可以看到,provider主要包括两个配制,一个是name:用于搜索用的唯一provider名称;type:工作类的程序集和类,一定要按照"类,程序集"的顺序,不然会出错的哦,不信你试试!当然还有其它配制,在CS中可以将其它配制存在一个NameValueCollection中,这样就可以随便扩展而不要写他的实体类了,这也是值得我们学习的地方啊。

  知道了配置文件,我们可以从CSConfiguration.cs文件中找到Provider的实体类,通过CSConfiguration类将其读取并缓存,这样能提高效率。关于怎样读取,我想回用XML的人都懂得,这里就不多说了,下面来看看代码。
ProviderEntity
 1    public class Provider 
 2    {
 3        string name;
 4        ExtensionType extensionType;
 5        string providerType;
 6        NameValueCollection providerAttributes = new NameValueCollection();
 7
 8        public Provider (XmlAttributeCollection attributes) 
 9        {
10
11            // Set the name of the provider
12            //
13            name = attributes["name"].Value;
14
15            if (attributes["extensionType"] != null)
16            {
17                // Set the extension type
18                //
19                try
20                {
21                    extensionType = (ExtensionType)Enum.Parse(typeof(ExtensionType), attributes["extensionType"].Value, true);
22                }

23                catch
24                {
25                    // Occassionally get an exception on parsing the extensiontype, so set it to Unknown
26                    extensionType = ExtensionType.Unknown;
27                }

28            }

29            // Set the type of the provider
30            //
31            providerType = attributes["type"].Value;
32
33            // Store all the attributes in the attributes bucket
34            //
35            foreach (XmlAttribute attribute in attributes) 
36            {
37                if ( (attribute.Name != "name") && (attribute.Name != "type") )
38                    providerAttributes.Add(attribute.Name, attribute.Value);
39            }

40        }

41
42        public string Name {
43            get {
44                return name;
45            }

46        }

47
48        public ExtensionType ExtensionType
49        {
50            get { return extensionType; }
51        }

52
53        public string Type {
54            get {
55                return providerType;
56            }

57        }

58
59        public NameValueCollection Attributes {
60            get {
61                return providerAttributes;
62            }

63        }

64
65    }

  Nme就是上面所说的配置节点中的name属性;Type就是type属性,将其他的如ConnectionString等保存在Attributes中,我们可以通过key&value来读取。到这里我们已经读取了provider配置,但要实现provider还需要通过反射技术,在DataProviders可以看到,这个类主要用于数据库的扩展类,一些非数据库的类大多用SingletonProviderHelper来实现,原理都差不多,主要DataProviders通过查找最匹配的具有(string connectionString,string dataOwrer)来对其实例化,在CSlReWriter类中就可以看到用SingletonProviderHelper来对其虚函数进行实例化。

  1public sealed class DataProviders
  2    {
  3        /**//// <summary>
  4        /// This class can not be instantiated
  5        /// </summary>

  6        private DataProviders()
  7        {
  8        }

  9
 10        private static void GetDataStoreParameters(Provider dataProvider, out string connectionString, out string databaseOwner)
 11        {
 12            databaseOwner = dataProvider.Attributes["databaseOwner"];
 13            if(databaseOwner == null || databaseOwner.Trim().Length == 0)
 14                databaseOwner = ConfigurationSettings.AppSettings[dataProvider.Attributes["databaseOwnerStringName"]];
 15
 16            connectionString = dataProvider.Attributes["connectionString"];
 17            if(connectionString == null || connectionString.Trim().Length == 0)
 18                connectionString = ConfigurationSettings.AppSettings[dataProvider.Attributes["connectionStringName"]];
 19        }

 20
 21        /**//// <summary>
 22        /// Creates an instance of the provider using Activator. This instance should be
 23        /// cached since it is an expesivie operation
 24        /// </summary>

 25        public static object CreateInstance(Provider dataProvider)
 26        {
 27            //Find the current attributes
 28            string connectionString = null; //dataProvider.Attributes["connectionString"];
 29            string databaseOwner = null;// dataProvider.Attributes["databaseOwner"];
 30
 31            GetDataStoreParameters(dataProvider, out connectionString, out databaseOwner);
 32
 33            //Get the type
 34            Type type  = Type.GetType(dataProvider.Type);
 35
 36            object newObject = null;
 37            if(type != null)
 38            {
 39                newObject =  Activator.CreateInstance(type,new object[]{databaseOwner,connectionString});  
 40            }

 41            
 42            if(newObject == null) //If we can not create an instance, throw an exception
 43                ProviderException(dataProvider.Name);
 44
 45            return newObject;
 46        }

 47
 48        /**//// <summary>
 49        /// Creates and Caches the ConstructorInfo for the specified provider. 
 50        /// </summary>

 51        public static ConstructorInfo CreateConstructorInfo (Provider dataProvider) 
 52        {
 53
 54            // The assembly should be in \bin or GAC, so we simply need
 55            // to get an instance of the type
 56            //
 57            CSConfiguration config = CSConfiguration.GetConfig();
 58            ConstructorInfo providerCnstr = null;
 59            try 
 60            {
 61                //string providerTypeName = ((Provider) config.Providers[providerName]).Type;
 62                Type type  = Type.GetType( dataProvider.Type );
 63
 64                // Insert the type into the cache
 65                //
 66                Type[] paramTypes = new Type[2];
 67                paramTypes[0] = typeof(string);
 68                paramTypes[1] = typeof(string);
 69
 70                providerCnstr = type.GetConstructor(paramTypes);
 71
 72            }
 
 73            catch 
 74            {
 75                ProviderException(dataProvider.Name);
 76            }

 77
 78           if(providerCnstr == null)
 79               ProviderException(dataProvider.Name);
 80
 81            return providerCnstr;
 82        }

 83
 84        /**//// <summary>
 85        /// Creates an instance of the specified provider using the Cached
 86        /// ConstructorInfo from CreateConstructorInfo
 87        /// </summary>

 88        public static object Invoke(Provider dataProvider)
 89        {
 90            object[] paramArray = new object[2];
 91
 92            
 93            string dbOwner = null; 
 94            string connstring = null;
 95
 96            GetDataStoreParameters(dataProvider, out connstring, out dbOwner);
 97
 98            paramArray[0] = dbOwner;
 99            paramArray[1] = connstring;
100
101            return CreateConstructorInfo(dataProvider).Invoke(paramArray);
102        }

103
104        Exception#region Exception
105        private static void ProviderException(string providerName)
106        {
107            CSConfiguration config = CSConfiguration.GetConfig();
108            HttpContext context = HttpContext.Current;
109            if (context != null) 
110            {
111                    
112                // We can't load the dataprovider
113                //
114                StreamReader reader = new StreamReader( context.Server.MapPath("~/Languages/" + config.DefaultLanguage + "/errors/DataProvider.htm") );
115                string html = reader.ReadToEnd();
116                reader.Close();
117
118                html = html.Replace("[DATAPROVIDERCLASS]", providerName);
119                html = html.Replace("[DATAPROVIDERASSEMBLY]", providerName);
120                context.Response.Write(html);
121                context.Response.End();
122            }
 
123            else 
124            {
125                throw new CSException(CSExceptionType.DataProvider, "Unable to load " + providerName);
126            }

127        }

128        #endregion

  通过Type.GetType()来进行类的反射,当然我们需要对其进行实例化才能调用abstract class中的方法和属性,这就要用到Activator.CreateInstance(type,new object[]{databaseOwner,connectionString}),这个方法对类进行了实例化,当然实例化这个类的构造函数中的参数为(databaseOwner,connectionString);当查找到这个构造函数进行实例化时也将DataProvider中所得到的databaseOwner,connectionString两个变量的值传递给了参数。

  OK这样就完成了整个实现过程,如果有不对的地方请批评指正!

关于作者:网魂小兵

文章出处:http://xdotnet.cnblogs.com

本文可以随意转载,摘抄等非商业用途。

为了尊重作者成果,在转载和摘抄的时候请留下作者名称和出处。

绿色通道:好文要顶关注我收藏该文与我联系
posted @ 2006-10-15 12:28 网魂小兵 阅读(502) 评论(0) 编辑 收藏
注册用户登录后才能发表评论,请 登录 或 注册,返回博客园首页。
首页博问闪存新闻园子招聘知识库
最新IT新闻:
· 最想要的Entity Framework功能
· 专访Jeffrey Richter:Windows 8是微软的重中之重
· 《福布斯》:谷歌进军硬件产品 难撼动苹果地位
· 美国空军拟最多购买1.8万台iPad 2
· 分析称专利之争让谷歌苹果两败俱伤
» 更多新闻...
最新知识库文章:
· 高级编程语言的发展历程
· 如何学习一门新的编程语言?
· 学习不同编程语言的重要性
· 为什么我喜欢富于表达性的编程语言
· 计算机专业的女生为什么要学编程
» 更多知识库文章...

China-pub 2011秋季教材巡展
China-Pub 计算机绝版图书按需印刷服务
Copyright ©2012 网魂小兵
Name:
网魂小兵
Addr:
福建厦门
MSN:
myxbing#hotmail.com
昵称:网魂小兵
园龄:5年11个月
粉丝:23
关注:0

搜索

 
 

常用链接

  • 我的随笔
  • 我的评论
  • 我的参与
  • 最新评论
  • 我的标签
  • 更多链接

我的标签

  • directx11(6)
  • direct3d 11(6)
  • 游戏编程(6)
  • c/c++(6)
  • vs2010(5)
  • wpf(4)
  • openssl(2)
  • direct3d坐标系(2)
  • vs2008(2)
  • xaml(2)
  • 更多

随笔分类(170)

  • AJAX(doc)(8)
  • ASP.NET(46)
  • C#3.0+(13)
  • C/C++(27)
  • CommunityServer(7)
  • Database(11)
  • Enterprise Library (7)
  • JavaScript(10)
  • ServerContols(7)
  • UML(1)
  • VC++/MFC(8)
  • WPF/SilverLight(6)
  • XNA Game(2)
  • 翻译(4)
  • 今天我当家(11)
  • 设计模式(2)

随笔档案(133)

  • 2012年2月 (3)
  • 2011年8月 (3)
  • 2011年7月 (7)
  • 2011年5月 (1)
  • 2011年4月 (2)
  • 2011年2月 (1)
  • 2010年1月 (1)
  • 2009年3月 (3)
  • 2009年1月 (8)
  • 2008年3月 (1)
  • 2008年2月 (3)
  • 2008年1月 (1)
  • 2007年11月 (4)
  • 2007年10月 (3)
  • 2007年9月 (9)
  • 2007年8月 (3)
  • 2007年7月 (2)
  • 2007年6月 (9)
  • 2007年5月 (9)
  • 2007年4月 (14)
  • 2007年3月 (6)
  • 2007年2月 (3)
  • 2007年1月 (15)
  • 2006年12月 (9)
  • 2006年11月 (2)
  • 2006年10月 (4)
  • 2006年9月 (7)

文章分类

  • Asp.Net(.NET)

I Like Links

  • ASP.NET
  • Codeplex
  • XNADevelopment

My Friend's Blog

  • 陆巍杰
  • 孙小雨
  • 探丫头
  • 网络安全&Linux

积分与排名

  • 积分 - 283912
  • 排名 - 248

最新评论

阅读排行榜

评论排行榜