在asp.net 2.0中有專門的Profile Provider用於為User Profile提供下層的儲存服務。(如果你對User Profile不熟悉,請看http://www.cnblogs.com/tonyqus/archive/2005/12/18/userprofilev2.html)
當然,asp.net也允許我們定製自訂的User Profile Provider,這為多伺服器或多種儲存介質提供了方便。比如我們可以把Profile儲存在Oracle的伺服器上,通過實現System.Web.Profile.ProfileProvider抽象類別自訂一個OracleProfileProvider就可以滿足這樣的需求。但通常我們都是在web.config中設定defaultProvider來切換Provider的,這意味著我們無法在運行時修改Provider。如果要用SqlProfileProvider就必須一直使用它。但這無法滿足一些特殊的項目需求,比如根據使用者的不同,使用不同的Profile資料庫。
於是我在網上找了很多資料,但都沒有有關如何在運行時修改Profile Provider的方法,只看到如何在運行時修改Membership Provider以及如何自訂Profile Provider的文章。為了實現這一點,特地用Reflector分析了預設的儲存方法。得出的結論如下:
假設我們在web.config中有這樣的profile設定:
<profile defaultProvider="AspNetSqlProfileProvider">
<providers>
<clear/>
<add name="AspNetSqlProfileProvider" connectionStringName="strConnUserDB" type="System.Web.Profile.SqlProfileProvider" description="儲存Profile資料"/>
<add name="TextFileProfileProvider" type="CustomProviders.TextFileProfileProvider, CustomProviders" description="Text file profile provider"/>
</providers>
<properties>
<add name="test"/>
</properties>
</profile>
如果我們要讓Profile["test"]使用TextFileProfileProvider來儲存資料的話,我們可以用下面的語句:
ProfileCommon.Properties["test"].Provider = Profile.Providers["TextFileProfileProvider"];
Profile["test"] = "bbb";
下面我們來分析一下原理。
我們通常使用的Profile其實是一個ProfileCommon的一個執行個體,Profile.Providers屬性提供了在web.config的providers節中設定的自訂Provider,我們可以用Profile.Providers["ProviderName"]這樣的代碼來獲得一個自訂Provider,注意這裡的ProviderName是providers節中的每一個provider的name屬性。由於Properties屬性是靜態屬性,無法通過ProfileCommon的執行個體來調用,所以只能用類調用。
在ProfileCommon類內部有一個SettingsPropertyCollection用於儲存所有的Profile屬性,而其中每個SettingsProperty就代表一個Profile屬性,對於每個SettingsProperty有三個必要元素:name, value和provider,這也是為什麼我們可以對某個Profile屬性設定provider。