asp.net Forums 之配置,缓存,多数据访问

在上一篇文章中,我谈到了asp.net Forums 之控件研究,这次我们来谈谈asp.net Forums 的配置、缓存和多数据访问。

一、配置

ANF的配置是通过ForumConfiguration类,ForumConfiguration类位于AspNetForums.Configuration命名空间下。

  

代码
   
     
#region VSS

/*
* $Header: /HiForums/Components/Configuration/ForumConfiguration.cs 1 05-10-26 15:04 Jacky $
*
* $History: ForumConfiguration.cs $
*
* ***************** Version 1 *****************
* User: Jacky Date: 05-10-26 Time: 15:04
* Created in $/HiForums/Components/Configuration
*
* ***************** Version 1 *****************
* User: Jacky Date: 05-10-21 Time: 14:20
* Created in $/HiForums/Components/Configuration
*
* ***************** Version 3 *****************
* User: Jacky Date: 05-09-20 Time: 19:23
* Updated in $/ASP.NET Forums/Components/Configuration
*
* ***************** Version 2 *****************
* User: Jacky Date: 05-09-20 Time: 1:36
* Updated in $/ASP.NET Forums/Components/Configuration
*/

#endregion

using System;
using System.Collections;
using System.Collections.Specialized;
using System.IO;
using System.Web;
using System.Web.Caching;
using System.Xml;
using System.Configuration;
using System.Xml.Serialization;
using AspNetForums.Components;
using AspNetForums.Enumerations;

namespace AspNetForums.Configuration
{
// *********************************************************************
// ForumConfiguration
//
/// <summary>
/// 读取论坛配置信息,根据CS结构重构.
/// by venjiang 2005/10/25
/// </summary>
///
// ***********************************************************************/
public class ForumConfiguration
{
#region 成员字段
public static readonly string CacheKey = " ForumsConfiguration " ;
private Hashtable providers = new Hashtable();
private Hashtable extensions = new Hashtable();
private static readonly Cache cache = HttpRuntime.Cache;
private string defaultProvider;
private string defaultLanguage;
private string forumFilesPath;
private bool disableBackgroundThreads = false ;
private bool disableIndexing = false ;
private bool disableEmail = false ;
private string passwordEncodingFormat = " unicode " ;
private int threadIntervalEmail = 15 ;
private int threadIntervalStats = 15 ;
// private SystemType systemType = SystemType.Self;
private short smtpServerConnectionLimit = - 1 ;
private bool enableLatestVersionCheck = true ;
private string uploadFilesPath = " /Upload/ " ;
private XmlDocument XmlDoc = null ;
#endregion

#region 构造器
public ForumConfiguration(XmlDocument doc)
{
XmlDoc
= doc;
LoadValuesFromConfigurationXml();
}
#endregion

#region 获取XML节点
public XmlNode GetConfigSection( string nodePath)
{
return XmlDoc.SelectSingleNode(nodePath);
}

#endregion
/*
public static ForumConfiguration GetConfig()
{
return (ForumConfiguration) ConfigurationSettings.GetConfig("forums/forums");
}
*/
#region 获取配置信息实例
public static ForumConfiguration GetConfig()
{
ForumConfiguration config
= cache.Get(CacheKey) as ForumConfiguration;
if (config == null )
{
string path;
if (HttpContext.Current != null )
path
= HttpContext.Current.Server.MapPath( " ~/Forums.config " );
else
path
= Directory.GetCurrentDirectory() + Path.DirectorySeparatorChar + " Forums.config " ;

XmlDocument doc
= new XmlDocument();
doc.Load(path);
config
= new ForumConfiguration(doc);
cache.Insert(CacheKey,config,
new CacheDependency(path),DateTime.MaxValue,TimeSpan.Zero,CacheItemPriority.AboveNormal, null );

// cache.ReSetFactor(config.CacheFactor);
}
return config;

}
#endregion

#region 加载配置文件设置
internal void LoadValuesFromConfigurationXml()
{
XmlNode node
= GetConfigSection( " Forums/Core " );
XmlAttributeCollection attributeCollection
= node.Attributes;

// 默认数据提供者
XmlAttribute att = attributeCollection[ " defaultProvider " ];
if (att != null )
defaultProvider
= att.Value;
// 默认语言
att = attributeCollection[ " defaultLanguage " ];
if (att != null )
defaultLanguage
= att.Value;
else
defaultLanguage
= " zh-CN " ;
// 论坛路径
att = attributeCollection[ " forumFilesPath " ];
if (att != null )
forumFilesPath
= att.Value;
else
forumFilesPath
= " / " ;
// 禁用后台线程
att = attributeCollection[ " disableThreading " ];
if (att != null )
disableBackgroundThreads
= bool .Parse(att.Value);
else
disableBackgroundThreads
= false ;
// 禁止索引
att = attributeCollection[ " disableIndexing " ];
if (att != null )
disableIndexing
= bool .Parse(att.Value);
else
disableIndexing
= false ;
// 禁止邮件
att = attributeCollection[ " disableEmail " ];
if (att != null )
disableEmail
= bool .Parse(att.Value);
else
disableEmail
= false ;
// 密码加密格式
att = attributeCollection[ " passwordEncodingFormat " ];
if (att != null )
passwordEncodingFormat
= att.Value;
else
passwordEncodingFormat
= " unicode " ;
// 后中统计状态
att = attributeCollection[ " threadIntervalStats " ];
if (att != null )
threadIntervalStats
= int .Parse(att.Value);
else
threadIntervalStats
= 15 ;
// 邮件队列发送间隔
att = attributeCollection[ " threadIntervalEmail " ];
if (att != null )
threadIntervalEmail
= int .Parse(att.Value);
else
threadIntervalEmail
= 15 ;
// SMTP服务器设置
att = attributeCollection[ " smtpServerConnectionLimit " ];
if (att != null )
smtpServerConnectionLimit
= short .Parse(att.Value);
else
smtpServerConnectionLimit
= - 1 ;
// 版本检查
att = attributeCollection[ " enableLatestVersionCheck " ];
if (att != null )
enableLatestVersionCheck
= bool .Parse(att.Value);
// 上传文件路径
att = attributeCollection[ " uploadFilesPath " ];
if (att != null )
uploadFilesPath
= att.Value;

// 读取子节点
foreach (XmlNode child in node.ChildNodes)
{
if (child.Name == " providers " )
GetProviders(child, providers);

if (child.Name == " extensionModules " )
GetProviders(child, extensions);

}
}

#endregion

#region 获取配置文件节点Provider
internal void GetProviders(XmlNode node, Hashtable table)
{
foreach (XmlNode provider in node.ChildNodes)
{
switch (provider.Name)
{
case " add " :
table.Add(provider.Attributes[
" name " ].Value, new Provider(provider.Attributes));
break ;

case " remove " :
table.Remove(provider.Attributes[
" name " ].Value);
break ;

case " clear " :
table.Clear();
break ;

}

}

}
#endregion

#region 公有属性
// Properties
//
public string DefaultLanguage
{
get { return defaultLanguage; }
}

public string ForumFilesPath
{
get { return forumFilesPath; }
}

public string DefaultProvider
{
get { return defaultProvider; }
}

public Hashtable Providers
{
get { return providers; }
}

public Hashtable Extensions
{
get { return extensions; }
}

public bool IsBackgroundThreadingDisabled
{
get { return disableBackgroundThreads; }
}

public bool IsIndexingDisabled
{
get { return disableIndexing; }
}

public string PasswordEncodingFormat
{
get { return passwordEncodingFormat; }
}

public string UploadFilesPath
{
get { return uploadFilesPath; }
}

public bool IsEmailDisabled
{
get { return disableEmail; }
}

public int ThreadIntervalEmail
{
get { return threadIntervalEmail; }
}

public int ThreadIntervalStats
{
get { return threadIntervalStats; }
}

public short SmtpServerConnectionLimit
{
get { return smtpServerConnectionLimit; }
}

public bool EnableLatestVersionCheck
{
get { return enableLatestVersionCheck; }
}
#endregion
}

/// <summary>
/// 数据提供者实体类
/// </summary>
public class Provider
{
#region 成员字段
private string name;
private string providerType;
private ExtensionType extensionType;
private NameValueCollection providerAttributes = new NameValueCollection();
#endregion

#region 构造器
public Provider(XmlAttributeCollection attributes)
{
// Set the name of the provider
//
name = attributes[ " name " ].Value;

// Set the extension type
//
try
{
extensionType
= (ExtensionType)Enum.Parse( typeof (ExtensionType), attributes[ " extensionType " ].Value, true );
}
catch
{
// Occassionally get an exception on parsing the extensiontype, so set it to Unknown
extensionType = ExtensionType.Unknown;
}

providerType
= attributes[ " type " ].Value;

// Store all the attributes in the attributes bucket
//
foreach (XmlAttribute attribute in attributes)
{
if ((attribute.Name != " name " ) && (attribute.Name != " type " ))
providerAttributes.Add(attribute.Name, attribute.Value);

}

}
#endregion

#region 公有属性
public string Name
{
get { return name; }
}

public string Type
{
get { return providerType; }
}

public ExtensionType ExtensionType
{
get { return extensionType; }
}


public NameValueCollection Attributes
{
get { return providerAttributes; }
}

#endregion
}
}
// *********************************************************************
// ForumsConfigurationHandler
//
/// <summary>
/// Class used by ASP.NET Configuration to load ASP.NET Forums configuration.
/// </summary>
///
// ***********************************************************************/
/*
internal class ForumsConfigurationHandler : IConfigurationSectionHandler
{
public virtual object Create(Object parent, Object context, XmlNode node)
{
ForumConfiguration config = new ForumConfiguration();
config.LoadValuesFromConfigurationXml(node);
return config;
}

}
*/

 

 

这个配置文件配置了ANF的默认数据提供者、默认语言、论坛路径、是滞禁用后台线程、是滞禁止索引、是否禁止邮件、密码加密格式、线程间隔状态、邮件队列发送间隔、SMTP服务器设置、版本检查
上传文件路径、数据提供者、自定义HttpModule等。主要方法为GetConfig():

 

代码
   
     
public static ForumConfiguration GetConfig()
{
ForumConfiguration config
= cache.Get(CacheKey) as ForumConfiguration;
if (config == null )
{
string path;
if (HttpContext.Current != null )
path
= HttpContext.Current.Server.MapPath( " ~/Forums.config " );
else
path
= Directory.GetCurrentDirectory() + Path.DirectorySeparatorChar + " Forums.config " ;

XmlDocument doc
= new XmlDocument();
doc.Load(path);
config
= new ForumConfiguration(doc);
cache.Insert(CacheKey,config,
new CacheDependency(path),DateTime.MaxValue,TimeSpan.Zero,CacheItemPriority.AboveNormal, null );

// cache.ReSetFactor(config.CacheFactor);
}
return config;

}

 

 

 

在此方法中,首先从Cache缓存中获取配置信息,如配置信息还未缓存,则读敢配置文件。配置文件位于网站根目录下的Forums.config文件。读取配置文件的内容后插入缓存中以便下次使用。
Forums.config文件如下:

 

代码
   
     
<? xml version = " 1.0 " encoding = " utf-8 " ?>
< Forums >
< Core defaultLanguage = " zh-CN "
forumFilesPath
= " / "
disableEmail
= " false "
disableIndexing
= " true "
disableThreading
= " false "
threadIntervalStats
= " 15 "
threadIntervalEmail
= " 15 "
smtpServerConnectionLimit
= " -1 "
passwordEncodingFormat
= " unicode "
enableLatestVersionCheck
= " false "
uploadFilesPath
= " /Upload/ "
defaultProvider
= " SqlForumsProvider " >
< providers >
< clear />
< add name = " LocalSqlForumsProvider " type = " AspNetForums.Data.SqlDataProvider, AspNetForums.SqlDataProvider "
connectionString
= " server=.;database=Forums;uid=sa;pwd= " databaseOwner = " dbo " />
< add name = " SqlForumsProvider " type = " AspNetForums.Data.SqlDataProvider, AspNetForums.SqlDataProvider "
connectionStringName
= " SiteSqlServer " databaseOwnerStringName = " SiteSqlServerOwner " />
< add name = " SqlDataProviderNonDbo " type = " AspNetForums.Data.SqlDataProviderNonDbo, AspNetForums.SqlDataProviderNonDbo "
connectionStringName
= " SiteSqlServer " databaseOwnerStringName = " SiteSqlServerOwner " />
</ providers >
< extensionModules >
< add name = " PassportAuthentication " extensionType = " Security " type = " Telligent.CommunityServer.Security.PassportAuthentication, Telligent.CommunityServer.SecurityModules " />
< add name = " WindowsAuthentication " extensionType = " Security " type = " Telligent.CommunityServer.Security.WindowsAuthentication, Telligent.CommunityServer.SecurityModules "
allowAutoUserRegistration
= " true " adminWindowsGroup = " Administrators " adminWindowsGroupIsSystemAdministrator = " true " />
< add name = " FormsAuthentication " extensionType = " Security " type = " Telligent.CommunityServer.Security.FormsAuthentication, Telligent.CommunityServer.SecurityModules "
allowAutoUserRegistration
= " true " userEmailAddressCookie = " CSUserEmailAddress " useEncryptedEmailAddressCookie = " false " />
</ extensionModules >
</ Core >
</ Forums >

 

 

二、缓存

通过在类中添加private static readonly Cache cache = HttpRuntime.Cache;来实现。

 

三、多数据访问

ANF的数据访问基类是ForumsDataProvider类,ForumsDataProvider这个类位于AspNetForums.Components命名空间下。这是一个抽象类,你可以去实现你的SQL子类或其他子类。主要方法为两个实例化方法。
实例化方法一:

  
    
public static ForumsDataProvider Instance()
{
// 理论上应该出现不了null,但程序运行确实出现过.原因待查.
if (_defaultInstance == null )
CreateDefaultCommonProvider();
return _defaultInstance;
}

       
在第一个实例化方法中,使用了单例设计模式,如果默认实例为空,则创建默认实例,方法如下:

 

代码
   
     
private static void CreateDefaultCommonProvider()
{
ForumConfiguration config
= ForumConfiguration.GetConfig();
Provider sqlForumsProvider
= (Provider) config.Providers[config.DefaultProvider];
_defaultInstance
= DataProviders.CreateInstance(sqlForumsProvider) as ForumsDataProvider;
}


首先获取配置信息,通过配置信息中的默认数据提供者来创建默认实例。

实例化方法二:

代码
   
     
public static ForumsDataProvider Instance (Provider dataProvider)
{
ForumsDataProvider fdp
= cache.Get(dataProvider.Name) as ForumsDataProvider;
if (fdp == null )
{
fdp
= DataProviders.Invoke(dataProvider) as ForumsDataProvider;
cache.Insert(dataProvider.Name,fdp,
null ,DateTime.MaxValue,TimeSpan.Zero,CacheItemPriority.AboveNormal, null );
}
return fdp;
}


在第二个实例化方法中,使用了缓存,通过给定的提供者,如果缓存中有,则直接调用。如果没有,则创建。创建后插入缓存以便下次使用。

 

其它抽象方法为子类需要实现的真正的数据访问方法。

 

欢迎大家指正。

你可能感兴趣的:(asp.net)