共同进退,荣辱与共(技术专栏)

技术专栏

  博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理

Provider的管理程序,反射就用他,保证好处多多。

配置文件还带智能提示功能哦,跟web.config一样。很爽。。。。

 

首先配置下web.config告诉系统配置文件在哪里。

 

<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>

 

在做个 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>

 

然后做个资源文件,存放架构信息。用来对配置文件(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;
        }


    }

}

 

使用就非常简单了。做个基类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);
}

 

有个例子,可以参考http://www.cnblogs.com/ttcre2/archive/2008/07/28/1251481.html

posted on 2008-07-28 13:14  猫咬狗  阅读(1128)  评论(0编辑  收藏  举报