基于Provider的自定义服务在使用 Membership 的时候可以为同一种操作方法定义多种行为,而具体使用哪种行为只需要在 Web.Config 中定义即可。 这样可以极大的促进了系统的灵活性,可是 Membership 这种 Provider 服务是怎么设计的呢?查了一些资料,也查看了 .Framework 2.0 的反编译源码,最终还是在 MSDN 上的一篇英文资料中找到了答案。 构建基于Provider的自定义服务 1、 首先构建一个 ImageProvider 它继承了 ProviderBase 类。 public abstract class ImageProvider : ProviderBase
{ // Properties public abstract string ApplicationName { get; set; } public abstract bool CanSaveImages { get; } // Methods public abstract Image RetrieveImage (string id); public abstract void SaveImage (string id, Image image); } public class ImageProviderCollection : ProviderCollection { public new ImageProvider this[string name] { get { return (ImageProvider) base[name]; } } public override void Add(ProviderBase provider) { if (provider == null) throw new ArgumentNullException("provider"); if (!(provider is ImageProvider)) throw new ArgumentException ("Invalid provider type", "provider"); base.Add(provider); } }
2、 我们先定义一个使用 SQL Server 的处理方法。
1[SqlClientPermission (SecurityAction.Demand, Unrestricted=true)]
2public class SqlImageProvider : ImageProvider 3{ 4 private string _applicationName; 5 private string _connectionString; 6 7 public override string ApplicationName 8 { 9 get { return _applicationName; } 10 set { _applicationName = value; } 11 } 12 13 public override bool CanSaveImages 14 { 15 get { return false; } 16 } 17 18 public string ConnectionStringName 19 { 20 get { return _connectionStringName; } 21 set { _connectionStringName = value; } 22 } 23 24 public override void Initialize (string name, 25 NameValueCollection config) 26 { 27 // Verify that config isn't null 28 if (config == null) 29 throw new ArgumentNullException ("config"); 30 31 // Assign the provider a default name if it doesn't have one 32 if (String.IsNullOrEmpty (name)) 33 name = "SqlImageProvider"; 34 35 // Add a default "description" attribute to config if the 36 // attribute doesn't exist or is empty 37 if (string.IsNullOrEmpty (config["description"])) { 38 config.Remove ("description"); 39 config.Add ("description", 40 "SQL image provider"); 41 } 42 43 // Call the base class's Initialize method 44 base.Initialize(name, config); 45 46 // Initialize _applicationName 47 _applicationName = config["applicationName"]; 48 49 if (string.IsNullOrEmpty(_applicationName)) 50 _applicationName = "/"; 51 52 config.Remove["applicationName"]; 53 54 // Initialize _connectionString 55 string connect = config["connectionStringName"]; 56 57 if (String.IsNullOrEmpty (connect)) 58 throw new ProviderException 59 ("Empty or missing connectionStringName"); 60 61 config.Remove ("connectionStringName"); 62 63 if (WebConfigurationManager.ConnectionStrings[connect] == null) 64 throw new ProviderException ("Missing connection string"); 65 66 _connectionString = WebConfigurationManager.ConnectionStrings 67 [connect].ConnectionString; 68 69 if (String.IsNullOrEmpty (_connectionString)) 70 throw new ProviderException ("Empty connection string"); 71 72 // Throw an exception if unrecognized attributes remain 73 if (config.Count > 0) { 74 string attr = config.GetKey (0); 75 if (!String.IsNullOrEmpty (attr)) 76 throw new ProviderException 77 ("Unrecognized attribute: " + attr); 78 } 79 } 80 81 public override Image RetrieveImage (string id) 82 { 83 // TODO: Retrieve an image from the database using 84 // _connectionString to open a database connection 85 } 86 87 public override void SaveImage (string id, Image image) 88 { 89 throw new NotSupportedException (); 90 } 91}
3. Web.Config 文件中配置 Image Service 1<configuration >
2 3 <connectionStrings> 4 <add name="ImageServiceConnectionString" connectionString="" /> 5 </connectionStrings> 6 <system.web> 7 <imageService defaultProvider="SqlImageProvider"> 8 <providers> 9 <add name="SqlImageProvider" type="SqlImageProvider" 10 connectionStringName="ImageServiceConnectionString"/> 11 </providers> 12 </imageService> 13 </system.web> 14</configuration>
结构节点<ImageServer> 现在系统是不可识别的,所有必需还要有一个相应的类用来描述 <ImageServer> 配置节。 4. <imageServer> 配置节的描述类 1using System;
2using System.Configuration; 3 4public class ImageServiceSection : ConfigurationSection 5{ 6 [ConfigurationProperty("providers")] 7 public ProviderSettingsCollection Providers 8 { 9 get { return (ProviderSettingsCollection) base["providers"]; } 10 } 11 12 [StringValidator(MinLength = 1)] 13 [ConfigurationProperty("defaultProvider", 14 DefaultValue = "SqlImageProvider")] 15 public string DefaultProvider 16 { 17 get { return (string) base["defaultProvider"]; } 18 set { base["defaultProvider"] = value; } 19 } 20} 21 22 这一下可以在 Web.Config 中注册 <imageService> 节了,并且它会被系统识别。 5. 创建 <imageService> 这个配置节的处理类
1<configuration >
2 <configSections> 3 <sectionGroup name="system.web"> 4 <section name="imageService" 5 type="ImageServiceSection, CustomSections" 6 allowDefinition="MachineToApplication" 7 restartOnExternalChanges="true" /> 8 </sectionGroup> 9 </configSections> 10 <connectionStrings> 11 <add name="ImageServiceConnectionString" connectionString="" /> 12 </connectionStrings> 13 <system.web> 14 <imageService defaultProvider="SqlImageProvider"> 15 <providers> 16 <add name="SqlImageProvider" type="SqlImageProvider" 17 connectionStringName="ImageServiceConnectionString"/> 18 </providers> 19 </imageService> 20 </system.web> 21</configuration> 22 23 现在可以加载并初始化自定义的 Providers 6、创建 ImageService 类,它将使用配置中的实例来处理
1using System;
2using System.Drawing; 3using System.Configuration; 4using System.Configuration.Provider; 5using System.Web.Configuration; 6using System.Web; 7 8public class ImageService 9{ 10 private static ImageProvider _provider = null; 11 private static ImageProviderCollection _providers = null; 12 private static object _lock = new object(); 13 14 public ImageProvider Provider 15 { 16 get { return _provider; } 17 } 18 19 public ImageProviderCollection Providers 20 { 21 get { return _providers; } 22 } 23 24 public static Image RetrieveImage(int imageID) 25 { 26 // Make sure a provider is loaded 27 LoadProviders(); 28 29 // Delegate to the provider 30 return _provider.RetrieveImage(imageID); 31 } 32 33 public static void SaveImage(Image image) 34 { 35 // Make sure a provider is loaded 36 LoadProviders(); 37 38 // Delegate to the provider 39 _provider.SaveImage(image); 40 } 41 42 private static void LoadProviders() 43 { 44 // Avoid claiming lock if providers are already loaded 45 if (_provider == null) 46 { 47 lock (_lock) 48 { 49 // Do this again to make sure _provider is still null 50 if (_provider == null) 51 { 52 // Get a reference to the <imageService> section 53 ImageServiceSection section = (ImageServiceSection) 54 WebConfigurationManager.GetSection 55 ("system.web/imageService"); 56 57 // Load registered providers and point _provider 58 // to the default provider 59 _providers = new ImageProviderCollection(); 60 ProvidersHelper.InstantiateProviders 61 (section.Providers, _providers, 62 typeof(ImageProvider)); 63 _provider = _providers[section.DefaultProvider]; 64 65 if (_provider == null) 66 throw new ProviderException 67 ("Unable to load default ImageProvider"); 68 } 69 } 70 } 71 } 72} 73 74 这些在 Asp.NET 2.0 中被支持。 |
|
来自: miky > 《VS.NET2008》