详解ProfileManager内部是如何运行的!
如大家要转载,请保留本人的版权:
/*
*Description:asp.NET自定义服务器控件内部细节系列教程
*Auther:崇崇-天真的好蓝
*MSN:chongchong2008@msn.com
*Blog:chongchong2008
*Dates:2007-05-20
*Copyright:ChongChong2008 YiChang HuBei China
*/
详解ProfileManager内部是如何运行的!
对于asp.NET2.0内置的profile有人支持,确也有不少高人说不过如此,所谓"鸡肋"!
那么下面我从它的设计意图,在代码层次上予以介绍,在完全了解了它的思想后我们也可以模仿这样的解决方案,如有错误之处还请高人指点!
先运行private static void Initialize (bool throwIfNotEnabled)
CODE如下:
private static void Initialize (bool throwIfNotEnabled)
{
ProfileManager.InitializeEnabled(true);
if (ProfileManager.s_InitException != null)
{
throw ProfileManager.s_InitException;
}
if (throwIfNotEnabled && !ProfileManager.s_Enabled)
{
throw new ProviderException(SR.GetString("Profile_not_enabled"));
}
}
在Initialize里面通过ProfileManager.InitializeEnabled(true)来实例化具体的Profile
CODE如下:
private static void InitializeEnabled (bool initProviders)
{
if (!ProfileManager.s_Initialized || !ProfileManager.s_InitializedProviders)
{
lock (ProfileManager.s_Lock)
{
if (ProfileManager.s_Initialized && ProfileManager.s_InitializedProviders)
{
return;
}
try
{
ProfileSection config = RuntimeConfig.GetAppConfig().Profile;
if (!ProfileManager.s_InitializedEnabled)
{
ProfileManager.s_Enabled = config.Enabled && HttpRuntime.HasAspNetHostingPermission(AspNetHostingPermissionLevel.Low);
ProfileManager.s_AutomaticSaveEnabled = ProfileManager.s_Enabled && config.AutomaticSaveEnabled;
ProfileManager.s_InitializedEnabled = true;
}
if ((initProviders && ProfileManager.s_Enabled) && !ProfileManager.s_InitializedProviders)
{
ProfileManager.InitProviders(config);
ProfileManager.s_InitializedProviders = true;
}
}
catch (Exception exception1)
{
ProfileManager.s_InitException = exception1;
}
ProfileManager.s_Initialized = true;
}
}
}
随后通过ProfileManager.InitProviders(config)具体来实例化
(这里的config是ProfileSection config = RuntimeConfig.GetAppConfig().Profile)
CODE如下:
private static void InitProviders (ProfileSection config)
{
ProfileManager.s_Providers = new ProfileProviderCollection();
if (config.Providers != null)
{
ProvidersHelper.InstantiateProviders(config.Providers, ProfileManager.s_Providers, typeof(ProfileProvider));
}
ProfileManager.s_Providers.SetReadOnly();
if (config.DefaultProvider == null)
{
throw new ProviderException(SR.GetString("Profile_default_provider_not_specified"));
}
ProfileManager.s_Provider = ProfileManager.s_Providers[config.DefaultProvider];
if (ProfileManager.s_Provider == null)
{
throw new ConfigurationErrorsException(SR.GetString("Profile_default_provider_not_found"), config.ElementInformation.Properties["providers"].Source, config.ElementInformation.Properties["providers"].LineNumber);
}
}
然后又通过ProvidersHelper.InstantiateProviders(config.Providers, ProfileManager.s_Providers, typeof(ProfileProvider))来处理
CODE如下:
[AspNetHostingPermission(SecurityAction.Demand, Level=AspNetHostingPermissionLevel.Low)]
public static void InstantiateProviders (ProviderSettingsCollection configProviders, ProviderCollection providers, Type providerType)
{
foreach (ProviderSettings providerSettings in configProviders)
{
providers.Add(ProvidersHelper.InstantiateProvider(providerSettings, providerType));
}
}
接着用ProvidersHelper.InstantiateProvider(providerSettings, providerType)的重载来来处理
CODE如下:
[AspNetHostingPermission(SecurityAction.Demand, Level=AspNetHostingPermissionLevel.Low)]
public static ProviderBase InstantiateProvider (ProviderSettings providerSettings, Type providerType)
{
ProviderBase base1 = null;
try
{
string value = (providerSettings.Type == null) ? null : providerSettings.Type.Trim();
if (string.IsNullOrEmpty(value))
{
throw new ArgumentException(SR.GetString("Provider_no_type_name"));
}
Type c = ConfigUtil.GetType(value, "type", providerSettings, true, true);
if (!providerType.IsAssignableFrom(c))
{
throw new ArgumentException(SR.GetString("Provider_must_implement_type", new object[]{providerType.ToString()}));
}
base1 = (ProviderBase) HttpRuntime.CreatePublicInstance(c);
NameValueCollection collection1 = providerSettings.Parameters;
NameValueCollection config = new NameValueCollection(collection1.Count, StringComparer.Ordinal);
foreach (string text2 in collection1)
{
config[text2] = collection1[text2];
}
base1.Initialize(providerSettings.Name, config);
}
catch (Exception exception1)
{
if (exception1 is ConfigurationException)
{
throw;
}
throw new ConfigurationErrorsException(exception1.Message, providerSettings.ElementInformation.Properties["type"].Source, providerSettings.ElementInformation.Properties["type"].LineNumber);
}
return base1;
}
然后交给 base1 = (ProviderBase) HttpRuntime.CreatePublicInstance(c)激活对象
CODE如下:
internal static object CreatePublicInstance (Type type)
{
return Activator.CreateInstance(type); //原来是在这里最终动态激活对象的
}
然后运行base1.Initialize(providerSettings.Name, config)
然后返回 base1 也就是 ProviderBase
最后static ProfileManager将所有需要完成具体操作的static class转交给Provider Attribute
Provider Attribute的实现如下
CODE如下:
public static ProfileProvider Provider
{
get
{
HttpRuntime.CheckAspNetHostingPermission(AspNetHostingPermissionLevel.Low, "Feature_not_supported_at_this_level");
ProfileManager.Initialize(true);
return ProfileManager.s_Provider;
}
}
也就是委托给了abstract ProviderBase类来完成工作
public abstract class ProviderBase
{
// Constructors
protected ProviderBase ();
// Methods
public virtual void Initialize (string name, NameValueCollection config);
// Properties
public virtual string Name { get; }
public virtual string Description { get; }
// Instance Fields
private string _name;
private string _Description;
private bool _Initialized;
}
而在web.config配置文件里定义了profile defaultProvider = SqlProfileProvider,当然这个是可以灵活扩展的,可以写你自己的ProfileProvider类.
SqlProfileProvider 继承 abstract ProfileProvider
CODE如下:
[AspNetHostingPermission(SecurityAction.InheritanceDemand, Level=AspNetHostingPermissionLevel.Minimal), AspNetHostingPermission(SecurityAction.LinkDemand, Level=AspNetHostingPermissionLevel.Minimal)]
public abstract class ProfileProvider : SettingsProvider
{
// Constructors
protected ProfileProvider ();
// Methods
public abstract int DeleteProfiles (ProfileInfoCollection profiles);
public abstract int DeleteProfiles (string[] usernames);
public abstract int DeleteInactiveProfiles (ProfileAuthenticationOption authenticationOption, DateTime userInactiveSinceDate);
public abstract int GetNumberOfInactiveProfiles (ProfileAuthenticationOption authenticationOption, DateTime userInactiveSinceDate);
public abstract ProfileInfoCollection GetAllProfiles (ProfileAuthenticationOption authenticationOption, int pageIndex, int pageSize, out int totalRecords);
public abstract ProfileInfoCollection GetAllInactiveProfiles (ProfileAuthenticationOption authenticationOption, DateTime userInactiveSinceDate, int pageIndex, int pageSize, out int totalRecords);
public abstract ProfileInfoCollection FindProfilesByUserName (ProfileAuthenticationOption authenticationOption, string usernameToMatch, int pageIndex, int pageSize, out int totalRecords);
public abstract ProfileInfoCollection FindInactiveProfilesByUserName (ProfileAuthenticationOption authenticationOption, string usernameToMatch, DateTime userInactiveSinceDate, int pageIndex, int pageSize, out int totalRecords);
}
[AspNetHostingPermission(SecurityAction.LinkDemand, Level=AspNetHostingPermissionLevel.Minimal), AspNetHostingPermission(SecurityAction.InheritanceDemand, Level=AspNetHostingPermissionLevel.Minimal)]
public class SqlProfileProvider : ProfileProvider
{
// Constructors
public SqlProfileProvider ();
// Methods
public override void Initialize (string name, NameValueCollection config);
private void CheckSchemaVersion (SqlConnection connection);
public override SettingsPropertyValueCollection GetPropertyValues (SettingsContext sc, SettingsPropertyCollection properties);
private void GetPropertyValuesFromDatabase (string userName, SettingsPropertyValueCollection svc);
public override void SetPropertyValues (SettingsContext sc, SettingsPropertyValueCollection properties);
private SqlParameter CreateInputParam (string paramName, SqlDbType dbType, object objValue);
public override int DeleteProfiles (ProfileInfoCollection profiles);
public override int DeleteProfiles (string[] usernames);
public override int DeleteInactiveProfiles (ProfileAuthenticationOption authenticationOption, DateTime userInactiveSinceDate);
public override int GetNumberOfInactiveProfiles (ProfileAuthenticationOption authenticationOption, DateTime userInactiveSinceDate);
public override ProfileInfoCollection GetAllProfiles (ProfileAuthenticationOption authenticationOption, int pageIndex, int pageSize, out int totalRecords);
public override ProfileInfoCollection GetAllInactiveProfiles (ProfileAuthenticationOption authenticationOption, DateTime userInactiveSinceDate, int pageIndex, int pageSize, out int totalRecords);
public override ProfileInfoCollection FindProfilesByUserName (ProfileAuthenticationOption authenticationOption, string usernameToMatch, int pageIndex, int pageSize, out int totalRecords);
public override ProfileInfoCollection FindInactiveProfilesByUserName (ProfileAuthenticationOption authenticationOption, string usernameToMatch, DateTime userInactiveSinceDate, int pageIndex, int pageSize, out int totalRecords);
private ProfileInfoCollection GetProfilesForQuery (SqlParameter[] args, ProfileAuthenticationOption authenticationOption, int pageIndex, int pageSize, out int totalRecords);
// Properties
public override string ApplicationName { get; set; }
private int CommandTimeout { get; }
// Instance Fields
private string _AppName;
private string _sqlConnectionString;
private int _SchemaVersionCheck;
private int _CommandTimeout;
}
也就是说最后的工作还是由SqlProfileProvider来完成的
[AspNetHostingPermission(SecurityAction.Demand, Level=AspNetHostingPermissionLevel.Low)]
public static ProviderBase InstantiateProvider (ProviderSettings providerSettings, Type providerType)
{
ProviderBase base1 = null;
try
{
string value = (providerSettings.Type == null) ? null : providerSettings.Type.Trim();
if (string.IsNullOrEmpty(value))
{
throw new ArgumentException(SR.GetString("Provider_no_type_name"));
}
Type c = ConfigUtil.GetType(value, "type", providerSettings, true, true);
if (!providerType.IsAssignableFrom(c))
{
throw new ArgumentException(SR.GetString("Provider_must_implement_type", new object[]{providerType.ToString()}));
}
base1 = (ProviderBase) HttpRuntime.CreatePublicInstance(c);
NameValueCollection collection1 = providerSettings.Parameters;
NameValueCollection config = new NameValueCollection(collection1.Count, StringComparer.Ordinal);
foreach (string text2 in collection1)
{
config[text2] = collection1[text2];
}
base1.Initialize(providerSettings.Name, config);
}
catch (Exception exception1)
{
if (exception1 is ConfigurationException)
{
throw;
}
throw new ConfigurationErrorsException(exception1.Message, providerSettings.ElementInformation.Properties["type"].Source, providerSettings.ElementInformation.Properties["type"].LineNumber);
}
return base1;
}
