如果初学的朋友也像我一样看了半天没有头绪,又找不到参考资料,在这里希望我个人对关于状态管理的部分理解会对你有所启发。
SettingsProperty 名称标识符+如何读写对象的描述,这些描述定义存取SettingsPropertyValue对象的方式。
是否将状态对象持久化,以及如何持久化。对应配置文件里两行。
SettingsPropertyCollection 元素类型是SettingsProperty的集合,通常作为参数传递。
SettingsPropertyValue pv = new SettingsPropertyValue(SettingsProperty);
需要关联一个SettingsProperty对象,描述了如何访问状态对象pv.PropertyValue。
pv.PropertyValue是我们真正关心的实例对象,需要实时维护的用户状态信息。
pv.Property 返回状态对象访问策略描述SettingsProperty,如:购物车对象是PetShop.BLL.Cart
类,用指定的自定义引擎读写,即时保存到数据库,需要时从数据库读取。
pv.Property.Name 配置文件中对应的标识符,如:"ShoppingCart"
pv.PropertyValue 内存中真正需要维护的状态对象,如:购物车对象user.Cart。
SettingsPropertyValueCollection 元素类型为SettingsPropertyValue的对象集合,通常作为参数传递。
用户访问网站时,应用程序后台服务需要记录用户的活动状态,用一个Profile实例,代替Session可以持久化到配置文件(数据库)中,也可以扩展需要记录的状态信息。
PetShop中自定义了类ProfileCommon。
ProfileCommon 继承于ProfileBase,继承于Properties,继承于SettingsBase
从ProfileBase继承了以下成员:
SettingsPropertyCollection Properties; //PropertyValues读写策略
SettingsPropertyValueCollection PropertyValues; //状态信息中需要维护(读写)的实例集合
SettingsContext Context; //当前用户及应用程序信息
从ProfileBase继承了以下方法:
public object GetPropertyValue(string propertyName); //可能从文件或数据库中读取,返回实例
public void SetPropertyValue(string propertyName, object propertyValue); //要保存的对象是object类型
public static SettingsPropertyCollection Properties { get; } //从配置文件中获取读写对象的方式
定义了以下可读写属性:
public class ProfileCommon : System.Web.Profile.ProfileBase ... { //扩展的用户状态类
public virtual PetShop.BLL.Cart ShoppingCart ...{ //可读写用户状态对象购物车的属性
get ...{
return ((PetShop.BLL.Cart)(this.GetPropertyValue("ShoppingCart"))); //访问购物车对象
}
set ...{
this.SetPropertyValue("ShoppingCart", value); //设置购物车对象
}
}
public virtual PetShop.BLL.Cart WishList ...{get; set;} //略
public virtual PetShop.Model.AddressInfo AccountInfo ...{ get ;set;} //略,用户地址信息
public virtual ProfileCommon GetProfile(string username) ...{
return ((ProfileCommon)(ProfileBase.Create(username)));
}
}
ASP.NET2中创建WebForm同时,自动为每个ASPX页面类声明一个类型为ProfileCommon的成员变量Profile。
当需要保存一个用户的购物车信息时,如果用Session,传统的方式是:
Session["AddressInfo"] = user.Cart;
在ASP.NET2中可以这样写:
Profile.AddressInfo = user.Cart;
当设置Profile时,会调用ProfileBase.SetPropertyValue(string propertyName, object propertyValue);
如果应用要将地址信息保存在数据库中,显然没有足够的信息,如变量propertyValue的类型,如何持久化等信息。于是调用ProfileBase.Properties从配置文件中获取写入操作所需要的信息,生成SettingsProperty实例。
创建读写引擎SettingsProperty.SettingsProvider,调用实现的接口函数SettingsProvider.SetProPertyValues(SettingsContext Context,SettingsPropertyValueCollection PropertyValues),完成对象写入工作。
为了能用更直观有效的方式存取购物车对象,ASP.NET2做了很多工作。
ProfileProvider 维护用户状态信息的引擎类,继承自SettingsProvider,继承自ProviderBase。
1.ProviderBase类声明了读取和写入状态信息的两个接口函数。
写入状态信息会引发SetProPertyValues()接口函数的调用,参数是一个SettingsPropertyValueCollection对象,关联一个用户在一个站点活动时的一组状态。每个元素是SettingsPropertyValue对象,SettingsPropertyValue.PropertyValue是真正需要关心的业务逻辑对象,对该对象的存取策略由SettingsPropertyValue.Property定义,属于SettingsProperty类的一个实例,可以在配置文件中配置。根据配置的策略,对象值可以在内存或临时文件中维护,或持久化到数据库中。
这部分可自定义对象存取策略的能力在基类SettingsProvider中声明,这个驱动类根据配置文件中的策略配置实例化一个策略SettingsProperty,来定制状态值SettingsPropertyValu.Property的存取方式。
根据配置文件中的配置信息(Setting的含义)可以生成一个SettingsProperty对象,需要设置值时,调用SettingsProperty.Provider对象的SetProPertyValues()方法。SettingsProperty.Provider是SettingsProvider类的实例,根据配置文件中的配置,运用策略模式,由引擎管理的工厂类动态创建。
<providers>
<add name="ShoppingCartProvider" connectionStringName="SQLProfileConnString" type="PetShop.Profile.PetShopProfileProvider" applicationName=".NET Pet Shop 4.0"/>
</providers>
<properties>
<add name="ShoppingCart" type="PetShop.BLL.Cart" allowAnonymous="true" provider="ShoppingCartProvider"/>
</properties>
2.ProfileProvider扩展了SettingsProvider的能力。只要实现ProfileProvider类接口,即可自定义增删用户状态信息。也运用策略模式动态初始化实例,配置信息与SettingsProvider实例的创建共享。
ProfileProvider接口部分成员函数由应用程序自动调用,实现该接口可以维护用户站内活动相关的更多状态信息。
接口成员函数:
SettingsProvider.GetPropertyValues()
传入SettingsProperty集合,返回SettingsPropertyValue集合,依据状态对象的存取策略获取状态对象值。
这个函数在系统需要获取用户信息ProfileCommon时引发,SettingsProperty值从配置文件中读取并初始化。
SettingsProvider.SetPropertyValues()
传入SettingsPropertyValue集合。保存内存中的状态对象值,可以根据保存策略决定是否持久化到数据库中。
其实这个函数是保存用户信息ProfileCommon.Save()时被触发,SettingsPropertyValue的值对应ProfileCommon用户状态信息的值。
ProfileProvider.DeleteProfiles() 删除用户状态信息。用户状态信息包括自定义的状态对象。
DeleteInactiveProfiles(ProfileAuthenticationOption authenticationOption, DateTime userInactiveSinceDate) 删除不活动过期用户。先得到用户列表,再执行删除。
FindProfilesByUserName(ProfileAuthenticationOption authenticationOption, string usernameToMatch, int pageIndex, int pageSize, out int totalRecords) 根据用户名查找状态对象
ProfileInfoCollection GetAllProfiles(ProfileAuthenticationOption authenticationOption, int pageIndex, int pageSize, out int totalRecords)
GetNumberOfInactiveProfiles(ProfileAuthenticationOption authenticationOption, DateTime userInactiveSinceDate)
ProfileInfoCollection GetProfileInfo(ProfileAuthenticationOption authenticationOption, string usernameToMatch, object userInactiveSinceDate, int pageIndex, int pageSize, out int totalRecords) 登录信息等。
public class CustomProfileInfo 简单地记录用户登录状态等信息。
最后还有一个状态信息总管ProfileManager,静态方法ProfileManager.DeleteProfile(username),会引发ProfileProvider.DeleteProfiles(username)
没有.NET源码,MSDN描述也不够详尽,不是我不求甚解,实在是暂时解不开,将来理解后,再逐步更新此文档。若误人子弟,概不负责。有错误之处,请路过的高人指正。