Provider的管理程序,反射就用他,保证好处多多。
配置文件还带智能提示功能哦,跟web.config一样。很爽。。。。
首先配置下web.config告诉系统配置文件在哪里。
<appSettings>
<add key="ProviderSettingsPath" value="~/Config/ProviderSettings.config" />
<!--<add key="UserInfoProviderName" value="UserInfoProvider" />-->
</appSettings>
<add key="ProviderSettingsPath" value="~/Config/ProviderSettings.config" />
<!--<add key="UserInfoProviderName" value="UserInfoProvider" />-->
</appSettings>
然后做个xml的架构文件 ProviderSchema.xsd 就和上面设置的 ProviderSetting.config 放一起好了。
<?xml version="1.0" encoding="utf-8"?>
<xs:schema id="ProviderSchema" elementFormDefault="qualified" xmlns="http://www.w3school.com.cn" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:NS="http://www.w3school.com.cn" targetNamespace="http://www.w3school.com.cn">
<xs:element name="ProviderCinfig">
<xs:complexType>
<xs:sequence minOccurs="0" maxOccurs="1">
<xs:element name="Providers">
<xs:complexType>
<xs:choice minOccurs="1" maxOccurs="unbounded">
<xs:element name="Provider">
<xs:complexType>
<xs:sequence minOccurs="0">
<xs:element name="Attributes">
<xs:complexType>
<xs:sequence minOccurs="1" maxOccurs="unbounded">
<xs:element name="add">
<xs:complexType>
<xs:sequence />
<xs:attribute name="key" type="xs:string" />
<xs:attribute name="value" type="xs:string" />
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:complexType>
<xs:key name="AttributesKey1">
<xs:selector xpath=".//NS:add" />
<xs:field xpath="@key" />
</xs:key>
</xs:element>
</xs:sequence>
<xs:attribute name="providerName" type="xs:string" />
<xs:attribute name="classType" type="xs:string" use="required" />
<xs:attribute name="assemblyType" type="xs:string" use="required" />
</xs:complexType>
</xs:element>
</xs:choice>
</xs:complexType>
<xs:key name="ProvidersKey1">
<xs:selector xpath=".//NS:Provider" />
<xs:field xpath="@providerName" />
</xs:key>
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:schema>
<xs:schema id="ProviderSchema" elementFormDefault="qualified" xmlns="http://www.w3school.com.cn" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:NS="http://www.w3school.com.cn" targetNamespace="http://www.w3school.com.cn">
<xs:element name="ProviderCinfig">
<xs:complexType>
<xs:sequence minOccurs="0" maxOccurs="1">
<xs:element name="Providers">
<xs:complexType>
<xs:choice minOccurs="1" maxOccurs="unbounded">
<xs:element name="Provider">
<xs:complexType>
<xs:sequence minOccurs="0">
<xs:element name="Attributes">
<xs:complexType>
<xs:sequence minOccurs="1" maxOccurs="unbounded">
<xs:element name="add">
<xs:complexType>
<xs:sequence />
<xs:attribute name="key" type="xs:string" />
<xs:attribute name="value" type="xs:string" />
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:complexType>
<xs:key name="AttributesKey1">
<xs:selector xpath=".//NS:add" />
<xs:field xpath="@key" />
</xs:key>
</xs:element>
</xs:sequence>
<xs:attribute name="providerName" type="xs:string" />
<xs:attribute name="classType" type="xs:string" use="required" />
<xs:attribute name="assemblyType" type="xs:string" use="required" />
</xs:complexType>
</xs:element>
</xs:choice>
</xs:complexType>
<xs:key name="ProvidersKey1">
<xs:selector xpath=".//NS:Provider" />
<xs:field xpath="@providerName" />
</xs:key>
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:schema>
在做个 ProviderSetting.config 文件,用来存放要反射文件的配置。参数很明显,一看就知道。
顺便解释下每个provider可以带很多个参数哦。而且设置下面的provider都是智能提示的,原来写配置文件可以这么简单。
<?xml version="1.0" encoding="utf-8"?>
<ProviderCinfig xmlns="http://www.w3school.com.cn" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.w3school.com.cn ProviderSchema.xsd">
<Providers>
<Provider providerName="AuthorCacheProvider" assemblyType="CE.SqlString.SqlStringTest.Provider, Version=1.0.0.0, Culture=neutral, PublicKeyToken=0aadabd12e7a8989" classType="CE.SqlString.SqlStringTest.Provider.AuthorProvider">
<Attributes>
<add key="getString" value="ttcre2"/>
</Attributes>
</Provider>
<Provider providerName="AuthorDalProvider" classType="CE.SqlString.SqlStringTest.Dal.AuthorDal" assemblyType="CE.SqlString.SqlStringTest.Dal, Version=1.0.0.0, Culture=neutral, PublicKeyToken=0aadabd12e7a8989" />
<Provider providerName="UserInfoProvider" classType="CE.Components.Base.Security.UserInfo" assemblyType="CE.Components.Base, Version=1.0.0.0, Culture=neutral, PublicKeyToken=209c90b915362a04" />
</Providers>
</ProviderCinfig>
<ProviderCinfig xmlns="http://www.w3school.com.cn" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.w3school.com.cn ProviderSchema.xsd">
<Providers>
<Provider providerName="AuthorCacheProvider" assemblyType="CE.SqlString.SqlStringTest.Provider, Version=1.0.0.0, Culture=neutral, PublicKeyToken=0aadabd12e7a8989" classType="CE.SqlString.SqlStringTest.Provider.AuthorProvider">
<Attributes>
<add key="getString" value="ttcre2"/>
</Attributes>
</Provider>
<Provider providerName="AuthorDalProvider" classType="CE.SqlString.SqlStringTest.Dal.AuthorDal" assemblyType="CE.SqlString.SqlStringTest.Dal, Version=1.0.0.0, Culture=neutral, PublicKeyToken=0aadabd12e7a8989" />
<Provider providerName="UserInfoProvider" classType="CE.Components.Base.Security.UserInfo" assemblyType="CE.Components.Base, Version=1.0.0.0, Culture=neutral, PublicKeyToken=209c90b915362a04" />
</Providers>
</ProviderCinfig>
然后做个资源文件,存放架构信息。用来对配置文件(ProviderSettings.config)做验证。
就是把ProviderSchema.xsd的内容记到一个字符串下面待用。我是放到配置文件中去了。
好了,关键的ProviderFactory.cs文件,代码如下。
using System;
using System.Collections.Generic;
using System.Text;
using System.Configuration;
using System.Configuration.Provider;
using System.Web.Configuration;
using System.Web.Caching;
using System.Web;
using System.IO;
using System.Xml;
using System.Xml.Schema;
using System.Xml.XPath;
using CE.Components.Base.Properties;
namespace CE.Components.Base
{
public sealed class ProviderFactory
{
private const string providerKey = "_CE_Components_Provider_CacheKey";
private static XmlSchemaSet xmlSchemaSet;
private ProviderFactory()
{
}
public static object LoadProvider(string providerName)
{
Cache cache;
ProviderSettingsCollection data;
//验证参数。
if (string.IsNullOrEmpty(providerName))
{
throw new ArgumentNullException("providerName");
}
//是否已缓存了配置?
cache = HttpRuntime.Cache;
data = cache[providerKey] as ProviderSettingsCollection;
//如果没有缓存。
if (data == null)
{
data = GetProviderSettingsCollection();
//把数据加入缓存。
SetCache(data);
}
//实例对象。
return ProvidersHelper.InstantiateProvider
(data[providerName], typeof(ProviderBase));
}
private static void SetCache(ProviderSettingsCollection data)
{
Cache cache;
CacheDependency dependency;
string providerSettingsPath;
cache = HttpRuntime.Cache;
//获取配置文件路径。
providerSettingsPath = ConfigurationManager.AppSettings["ProviderSettingsPath"];
//获取配置文件物理绝对路径。
providerSettingsPath = GetProviderSettingsPhysicsAbsolutePath(providerSettingsPath);
using (dependency = new CacheDependency(providerSettingsPath))
{
cache.Add(providerKey, data, dependency, Cache.NoAbsoluteExpiration, Cache.NoSlidingExpiration, CacheItemPriority.High, null);
}
}
private static ProviderSettingsCollection GetProviderSettingsCollection()
{
ProviderSettingsCollection returnValue;
string providerSettingsPath;
XPathNavigator xmlDocumentNavigator;
ProviderSettings providerSettings;
returnValue = new ProviderSettingsCollection();
//获取配置文件路径。
providerSettingsPath = ConfigurationManager.AppSettings["ProviderSettingsPath"];
//获取配置文件物理绝对路径。
providerSettingsPath = GetProviderSettingsPhysicsAbsolutePath(providerSettingsPath);
//验证sql配置文件。
//验证失败直接抛出异常。
//验证成功返回xpth,验证的时候必须read一次xml,成功了就直接返回。没必要read两次吧。
xmlDocumentNavigator = ValidateConfigFile(providerSettingsPath);
//是否有子节点。移动到了 Providers 节点。
if (xmlDocumentNavigator.MoveToChild(XPathNodeType.Element))
{
//移动到了 Provider 节点。
if (xmlDocumentNavigator.MoveToChild(XPathNodeType.Element))
{
do
{
providerSettings = GetProviderSettings
(xmlDocumentNavigator.CreateNavigator());
returnValue.Add(providerSettings);
} while (xmlDocumentNavigator.MoveToNext(XPathNodeType.Element));
}
}
return returnValue;
}
private static ProviderSettings GetProviderSettings(XPathNavigator xPathNavigator)
{
ProviderSettings providerSettings;
string providerName;
string assemblyType;
string classType;
providerSettings = new ProviderSettings();
//获取基本信息。
providerName = xPathNavigator.GetAttribute("providerName", "");
assemblyType = xPathNavigator.GetAttribute("assemblyType", "");
classType = xPathNavigator.GetAttribute("classType", "");
providerSettings.Name = providerName;
providerSettings.Type = classType + "," + assemblyType;
//加载用户自定义参数。
//移到 Attributes 节点。
if (xPathNavigator.MoveToChild(XPathNodeType.Element))
{
//移到 add 节点。
if (xPathNavigator.MoveToChild(XPathNodeType.Element))
{
do
{
providerSettings.Parameters.Add
(xPathNavigator.GetAttribute("key", ""),
xPathNavigator.GetAttribute("value", ""));
} while (xPathNavigator.MoveToNext(XPathNodeType.Element));
}
}
return providerSettings;
}
private static XPathNavigator ValidateConfigFile(string providerSettingsPath)
{
XmlDocument xmlDocument;
XmlReaderSettings settings;
XmlReader xmlReader;
xmlDocument = new XmlDocument();
settings = new XmlReaderSettings();
//读取时候验证架构。
settings.ValidationType = ValidationType.Schema;
settings.Schemas.Add(XmlSchemaSet);
using (xmlReader = XmlReader.Create(providerSettingsPath, settings))
{
xmlDocument.Load(xmlReader);
}
return xmlDocument.DocumentElement.CreateNavigator();
}
private static XmlSchemaSet XmlSchemaSet
{
get
{
string schemaText;
Stream stream;
byte[] buffer;
XmlReader reader;
if (null == xmlSchemaSet)
{
schemaText = Resources.ResourceManager.
GetString("XmlSchemaInfo");
buffer = Encoding.UTF8.GetBytes(schemaText);
xmlSchemaSet = new XmlSchemaSet();
using (stream = new MemoryStream(buffer))
{
reader = XmlReader.Create(stream);
xmlSchemaSet.Add("http://www.w3school.com.cn", reader);
}
}
return xmlSchemaSet;
}
}
/// <summary>
/// 获取配置文件物理绝对路径。
/// </summary>
/// <param name="providerSettingsPath"></param>
/// <returns></returns>
private static string GetProviderSettingsPhysicsAbsolutePath(string providerSettingsPath)
{
string path;
//验证参数。
if (string.IsNullOrEmpty(providerSettingsPath))
{
throw new ArgumentNullException("providerSettingsPath");
}
//如果是虚拟路径,我们把他转换成物理路径。
if (providerSettingsPath.IndexOf("~/") == 0 || providerSettingsPath.IndexOf("/") == 0)
{
path = HttpContext.Current.Server.MapPath(providerSettingsPath);
}
else
{
path = providerSettingsPath;
}
//文件是否存在。
if (!File.Exists(path))
{
throw new FileNotFoundException(Resources.ResourceManager
.GetString("FileNotFoundException"), path);
}
//获取绝对路径。
path = Path.GetFullPath(path);
return path;
}
}
}
using System.Collections.Generic;
using System.Text;
using System.Configuration;
using System.Configuration.Provider;
using System.Web.Configuration;
using System.Web.Caching;
using System.Web;
using System.IO;
using System.Xml;
using System.Xml.Schema;
using System.Xml.XPath;
using CE.Components.Base.Properties;
namespace CE.Components.Base
{
public sealed class ProviderFactory
{
private const string providerKey = "_CE_Components_Provider_CacheKey";
private static XmlSchemaSet xmlSchemaSet;
private ProviderFactory()
{
}
public static object LoadProvider(string providerName)
{
Cache cache;
ProviderSettingsCollection data;
//验证参数。
if (string.IsNullOrEmpty(providerName))
{
throw new ArgumentNullException("providerName");
}
//是否已缓存了配置?
cache = HttpRuntime.Cache;
data = cache[providerKey] as ProviderSettingsCollection;
//如果没有缓存。
if (data == null)
{
data = GetProviderSettingsCollection();
//把数据加入缓存。
SetCache(data);
}
//实例对象。
return ProvidersHelper.InstantiateProvider
(data[providerName], typeof(ProviderBase));
}
private static void SetCache(ProviderSettingsCollection data)
{
Cache cache;
CacheDependency dependency;
string providerSettingsPath;
cache = HttpRuntime.Cache;
//获取配置文件路径。
providerSettingsPath = ConfigurationManager.AppSettings["ProviderSettingsPath"];
//获取配置文件物理绝对路径。
providerSettingsPath = GetProviderSettingsPhysicsAbsolutePath(providerSettingsPath);
using (dependency = new CacheDependency(providerSettingsPath))
{
cache.Add(providerKey, data, dependency, Cache.NoAbsoluteExpiration, Cache.NoSlidingExpiration, CacheItemPriority.High, null);
}
}
private static ProviderSettingsCollection GetProviderSettingsCollection()
{
ProviderSettingsCollection returnValue;
string providerSettingsPath;
XPathNavigator xmlDocumentNavigator;
ProviderSettings providerSettings;
returnValue = new ProviderSettingsCollection();
//获取配置文件路径。
providerSettingsPath = ConfigurationManager.AppSettings["ProviderSettingsPath"];
//获取配置文件物理绝对路径。
providerSettingsPath = GetProviderSettingsPhysicsAbsolutePath(providerSettingsPath);
//验证sql配置文件。
//验证失败直接抛出异常。
//验证成功返回xpth,验证的时候必须read一次xml,成功了就直接返回。没必要read两次吧。
xmlDocumentNavigator = ValidateConfigFile(providerSettingsPath);
//是否有子节点。移动到了 Providers 节点。
if (xmlDocumentNavigator.MoveToChild(XPathNodeType.Element))
{
//移动到了 Provider 节点。
if (xmlDocumentNavigator.MoveToChild(XPathNodeType.Element))
{
do
{
providerSettings = GetProviderSettings
(xmlDocumentNavigator.CreateNavigator());
returnValue.Add(providerSettings);
} while (xmlDocumentNavigator.MoveToNext(XPathNodeType.Element));
}
}
return returnValue;
}
private static ProviderSettings GetProviderSettings(XPathNavigator xPathNavigator)
{
ProviderSettings providerSettings;
string providerName;
string assemblyType;
string classType;
providerSettings = new ProviderSettings();
//获取基本信息。
providerName = xPathNavigator.GetAttribute("providerName", "");
assemblyType = xPathNavigator.GetAttribute("assemblyType", "");
classType = xPathNavigator.GetAttribute("classType", "");
providerSettings.Name = providerName;
providerSettings.Type = classType + "," + assemblyType;
//加载用户自定义参数。
//移到 Attributes 节点。
if (xPathNavigator.MoveToChild(XPathNodeType.Element))
{
//移到 add 节点。
if (xPathNavigator.MoveToChild(XPathNodeType.Element))
{
do
{
providerSettings.Parameters.Add
(xPathNavigator.GetAttribute("key", ""),
xPathNavigator.GetAttribute("value", ""));
} while (xPathNavigator.MoveToNext(XPathNodeType.Element));
}
}
return providerSettings;
}
private static XPathNavigator ValidateConfigFile(string providerSettingsPath)
{
XmlDocument xmlDocument;
XmlReaderSettings settings;
XmlReader xmlReader;
xmlDocument = new XmlDocument();
settings = new XmlReaderSettings();
//读取时候验证架构。
settings.ValidationType = ValidationType.Schema;
settings.Schemas.Add(XmlSchemaSet);
using (xmlReader = XmlReader.Create(providerSettingsPath, settings))
{
xmlDocument.Load(xmlReader);
}
return xmlDocument.DocumentElement.CreateNavigator();
}
private static XmlSchemaSet XmlSchemaSet
{
get
{
string schemaText;
Stream stream;
byte[] buffer;
XmlReader reader;
if (null == xmlSchemaSet)
{
schemaText = Resources.ResourceManager.
GetString("XmlSchemaInfo");
buffer = Encoding.UTF8.GetBytes(schemaText);
xmlSchemaSet = new XmlSchemaSet();
using (stream = new MemoryStream(buffer))
{
reader = XmlReader.Create(stream);
xmlSchemaSet.Add("http://www.w3school.com.cn", reader);
}
}
return xmlSchemaSet;
}
}
/// <summary>
/// 获取配置文件物理绝对路径。
/// </summary>
/// <param name="providerSettingsPath"></param>
/// <returns></returns>
private static string GetProviderSettingsPhysicsAbsolutePath(string providerSettingsPath)
{
string path;
//验证参数。
if (string.IsNullOrEmpty(providerSettingsPath))
{
throw new ArgumentNullException("providerSettingsPath");
}
//如果是虚拟路径,我们把他转换成物理路径。
if (providerSettingsPath.IndexOf("~/") == 0 || providerSettingsPath.IndexOf("/") == 0)
{
path = HttpContext.Current.Server.MapPath(providerSettingsPath);
}
else
{
path = providerSettingsPath;
}
//文件是否存在。
if (!File.Exists(path))
{
throw new FileNotFoundException(Resources.ResourceManager
.GetString("FileNotFoundException"), path);
}
//获取绝对路径。
path = Path.GetFullPath(path);
return path;
}
}
}
使用就非常简单了。做个基类UserInfoBase,继承System.Configuration.Provider.ProviderBase
然后要类UserInfo继承UserInfoBase。
调用方法:
ProviderFactory.LoadProvider("配置文件中的那个名字") as UserInfoBase
调用参数的方法:
public override void Initialize(string name, System.Collections.Specialized.NameValueCollection config)
{
base.Initialize(name, config);
}
{
base.Initialize(name, config);
}
有个例子,可以参考http://www.cnblogs.com/ttcre2/archive/2008/07/28/1251481.html