如大家要轉載,請保留本人的著作權:
/*
*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;
}