BlogEngine.NET 1.5的BlogProvider、DbBlogProvider
(1)ProviderBase是个抽象类,这里主要关注其中的虚方法Initialize。
(2)BlogProvider也是一个抽象类,继承自ProviderBase,提供了自己的抽象方法,例如
public abstract Post SelectPost(Guid id);
public abstract void InsertPost(Post post);等等,
这些抽象方法的具体实现由BlogProvider类的派生类来实现,在这里拿DbBlogProvider类来讨论(另外一个是XmlBlogProvider)。
(3)DbBlogProvider类继承了BlogProvider类,实现了父类的抽象方法,用来实现增、删、查、改等等数据交互,DbBlogProvider类还重写了父类(BlogProvider)的父类(ProviderBase)的Initialize方法,大概是用来根据自定义的提供程序提取相应的信息,例如连接字符串等,这个自定义提供程序的选择,在BlogService类中的LoadProviders方法中进行。
(4)BlogProviderSection类中定义了自定义的配置节点的相关信息。
(5) BlogProviderCollection类继承自ProviderCollection类,重写了Add方法,代码如下
{
if (provider == null)
throw new ArgumentNullException("provider");
if (!(provider is BlogProvider))
throw new ArgumentException
("Invalid provider type", "provider");
base.Add(provider);
//为了看清楚base.Add(provider);,贴出ProviderCollection中的Add方法
//private Hashtable _Hashtable = new Hashtable(10, StringComparer.OrdinalIgnoreCase);
//public virtual void Add(ProviderBase provider)
//{
// if (this._ReadOnly)
// {
// throw new NotSupportedException(SR.GetString("CollectionReadOnly"));
// }
// if (provider == null)
// {
// throw new ArgumentNullException("provider");
// }
// if ((provider.Name == null) || (provider.Name.Length < 1))
// {
// throw new ArgumentException(SR.GetString("Config_provider_name_null_or_empty"));
// }
// this._Hashtable.Add(provider.Name, provider);
//}
(6)BlogService类的 LoadProviders方法
{
// Avoid claiming lock if providers are already loaded
if (_provider == null)
{
lock (_lock)
{
// Do this again to make sure _provider is still null
if (_provider == null)
{
// Get a reference to the <blogProvider> section
// 获取自定义的配置节
BlogProviderSection section = (BlogProviderSection)WebConfigurationManager.GetSection("BlogEngine/blogProvider");
// Load registered providers and point _provider
// to the default provider
// 载入已注册的默认自定义的提供程序
_providers = new BlogProviderCollection();
ProvidersHelper.InstantiateProviders(section.Providers, _providers, typeof(BlogProvider));
//section.Providers是一个ProviderSettingsCollection类型,_providers是一个ProviderCollection类型
//ProvidersHelper.InstantiateProviders实际上通过_providers的Add方法调用了一个它的重载方法,这个方法中创建一个ProviderBase对象,
//调用ProviderBase对象的Initialize方法初始化提供程序,返回一个ProviderBase类型的对象
_provider = _providers[section.DefaultProvider];
// 根据索引返回一个[DbBlogProvider]的BlogProvider对象给_provider
if (_provider == null)
throw new ProviderException("Unable to load default BlogProvider");
}
}
}
}
在LoadProviders方法中,先是通过自定义的配置节获取配置节点没,之后创建BlogProviderCollection对象,接着调用了ProvidersHelper.InstantiateProviders方法,该方法有2个重载,这里的ProvidersHelper.InstantiateProviders(section.Providers, _providers, typeof(BlogProvider));的具体实现如下:
public static void InstantiateProviders(ProviderSettingsCollection configProviders, ProviderCollection providers, Type providerType)
{
foreach (ProviderSettings settings in configProviders)
{
providers.Add(InstantiateProvider(settings, providerType));
// 在这里providers是BlogProviderCollection对象。
// InstantiateProvider(settings, providerType)是另一个重载方法,内部实现如下:
// [AspNetHostingPermission(SecurityAction.Demand, Level=AspNetHostingPermissionLevel.Low)]
//public static ProviderBase InstantiateProvider(ProviderSettings providerSettings, Type providerType)
//{
// ProviderBase base2 = null;
// try
// {
// string str = (providerSettings.Type == null) ? null : providerSettings.Type.Trim();
// if (string.IsNullOrEmpty(str))
// {
// throw new ArgumentException(SR.GetString("Provider_no_type_name"));
// }
// Type c = ConfigUtil.GetType(str, "type", providerSettings, true, true);
// if (!providerType.IsAssignableFrom(c))
// {
// throw new ArgumentException(SR.GetString("Provider_must_implement_type", new object[] { providerType.ToString() }));
// }
// base2 = (ProviderBase) HttpRuntime.CreatePublicInstance(c);
// 在这里通过HttpRuntime.CreatePublicInstance(c)动态创建指定类型的实例,
// HttpRuntime.CreatePublicInstance(c)其实就是调用了Activator.CreateInstance(type);
// 还有Assembly.CreateInstance()其实也是调用了Activator.CreateInstance(type);
// NameValueCollection parameters = providerSettings.Parameters;
// NameValueCollection config = new NameValueCollection(parameters.Count, StringComparer.Ordinal);
// foreach (string str2 in parameters)
// {
// config[str2] = parameters[str2];
// }
// base2.Initialize(providerSettings.Name, config);
// }
// catch (Exception exception)
// {
// if (exception is ConfigurationException)
// {
// throw;
// }
// throw new ConfigurationErrorsException(exception.Message, providerSettings.ElementInformation.Properties["type"].Source, providerSettings.ElementInformation.Properties["type"].LineNumber);
// }
// return base2;
//}
}
}
最后_provider = _providers[section.DefaultProvider]; ,因为之前已经通过方法ProvidersHelper.InstantiateProviders(section.Providers, _providers, typeof(BlogProvider));将所有的自定义提供程序的相关信息存储到Hashtable中,BlogProviderCollection类中有个索引
{
get { return (BlogProvider)base[name]; }
//base[name]的实现
//public ProviderBase this[string name]
//{
// get
// {
// return (this._Hashtable[name] as ProviderBase);
// }
//}
}
_providers[section.DefaultProvider]根据自定义配置节中的默认的自定义提供程序获取动态创建的实例,不管是DbBlogProvider类或者是其他类,只要继承BlogProvider,只要提供了父类抽象类的实现,只要在web.config中的自定义节中进行了配置,就可以通过_provider.具体方法()来进行具体的操作,不需要去知道底层是用什么方式实现。大概MembershipProvider也是这么实现的。