基于Provider的自定义服务

在使用 Membership 的时候可以为同一种操作方法定义多种行为,而具体使用哪种行为只需要在 Web.Config 中定义即可。

这样可以极大的促进了系统的灵活性,可是 Membership 这种 Provider 服务是怎么设计的呢?查了一些资料,也查看了 .Framework 2.0 的反编译源码,最终还是在 MSDN 上的一篇英文资料中找到了答案。
设计这种模式,似乎并不是那么容易,需要设计许多类方可。

构建基于Provider的自定义服务
下面是一个基本Provider的自定义服务的示例,它公开了两个操作方法“RetrieveImage”和“SaveImage”。它有可以会使用不同的数据库,这样可以定义多种处理方法。只需要在 Web.Config 中进行配置,就可以让系统调用相应的行为来进行处理。

1、 首先构建一个 ImageProvider 它继承了 ProviderBase 类。

None.gif public   abstract   class  ImageProvider : ProviderBase
ExpandedBlockStart.gifContractedBlock.gif
dot.gif {
InBlock.gif    
// Properties
ExpandedSubBlockStart.gifContractedSubBlock.gif
    public abstract string ApplicationName dot.gifgetset; }
ExpandedSubBlockStart.gifContractedSubBlock.gif    
public abstract bool CanSaveImages dot.gifget; }
InBlock.gif
InBlock.gif    
// Methods
InBlock.gif
    public abstract Image RetrieveImage (string id);
InBlock.gif    
public abstract void SaveImage (string id, Image image);
ExpandedBlockEnd.gif}

None.gif
None.gif
public   class  ImageProviderCollection : ProviderCollection
ExpandedBlockStart.gifContractedBlock.gif
dot.gif {
InBlock.gif    
public new ImageProvider this[string name]
ExpandedSubBlockStart.gifContractedSubBlock.gif    
dot.gif{
ExpandedSubBlockStart.gifContractedSubBlock.gif        
get dot.gifreturn (ImageProvider) base[name]; }
ExpandedSubBlockEnd.gif    }

InBlock.gif
InBlock.gif    
public override void Add(ProviderBase provider)
ExpandedSubBlockStart.gifContractedSubBlock.gif    
dot.gif{
InBlock.gif        
if (provider == null)
InBlock.gif            
throw new ArgumentNullException("provider");
InBlock.gif
InBlock.gif        
if (!(provider is ImageProvider))
InBlock.gif            
throw new ArgumentException
InBlock.gif                (
"Invalid provider type""provider");
InBlock.gif
InBlock.gif        
base.Add(provider);
ExpandedSubBlockEnd.gif    }

ExpandedBlockEnd.gif}

 

2、 我们先定义一个使用 SQL Server 的处理方法。

 

 1 None.gif [SqlClientPermission (SecurityAction.Demand, Unrestricted = true )]
 2 None.gif public   class  SqlImageProvider : ImageProvider
 3 ExpandedBlockStart.gifContractedBlock.gif dot.gif {
 4InBlock.gif    private string _applicationName;
 5InBlock.gif    private string _connectionString;
 6InBlock.gif
 7InBlock.gif    public override string ApplicationName
 8ExpandedSubBlockStart.gifContractedSubBlock.gif    dot.gif{
 9ExpandedSubBlockStart.gifContractedSubBlock.gif        get dot.gifreturn _applicationName; }
10ExpandedSubBlockStart.gifContractedSubBlock.gif        set dot.gif{ _applicationName = value; }
11ExpandedSubBlockEnd.gif    }

12InBlock.gif
13InBlock.gif    public override bool CanSaveImages
14ExpandedSubBlockStart.gifContractedSubBlock.gif    dot.gif{
15ExpandedSubBlockStart.gifContractedSubBlock.gif        get dot.gifreturn false; }
16ExpandedSubBlockEnd.gif    }

17InBlock.gif
18InBlock.gif    public string ConnectionStringName
19ExpandedSubBlockStart.gifContractedSubBlock.gif    dot.gif{
20ExpandedSubBlockStart.gifContractedSubBlock.gif        get dot.gifreturn _connectionStringName; }
21ExpandedSubBlockStart.gifContractedSubBlock.gif        set dot.gif{ _connectionStringName = value; }
22ExpandedSubBlockEnd.gif    }

23InBlock.gif
24InBlock.gif    public override void Initialize (string name,
25InBlock.gif        NameValueCollection config)
26ExpandedSubBlockStart.gifContractedSubBlock.gif    dot.gif{
27InBlock.gif        // Verify that config isn't null
28InBlock.gif        if (config == null)
29InBlock.gif            throw new ArgumentNullException ("config");
30InBlock.gif
31InBlock.gif        // Assign the provider a default name if it doesn't have one
32InBlock.gif        if (String.IsNullOrEmpty (name))
33InBlock.gif            name = "SqlImageProvider";
34InBlock.gif
35InBlock.gif        // Add a default "description" attribute to config if the
36InBlock.gif        // attribute doesn't exist or is empty
37ExpandedSubBlockStart.gifContractedSubBlock.gif        if (string.IsNullOrEmpty (config["description"])) dot.gif{
38InBlock.gif            config.Remove ("description");
39InBlock.gif            config.Add ("description",
40InBlock.gif                "SQL image provider");
41ExpandedSubBlockEnd.gif        }

42InBlock.gif
43InBlock.gif        // Call the base class's Initialize method
44InBlock.gif        base.Initialize(name, config);
45InBlock.gif
46InBlock.gif        // Initialize _applicationName
47InBlock.gif        _applicationName = config["applicationName"];
48InBlock.gif
49InBlock.gif        if (string.IsNullOrEmpty(_applicationName))
50InBlock.gif            _applicationName = "/";
51InBlock.gif
52InBlock.gif        config.Remove["applicationName"];
53InBlock.gif
54InBlock.gif        // Initialize _connectionString
55InBlock.gif        string connect = config["connectionStringName"];
56InBlock.gif
57InBlock.gif        if (String.IsNullOrEmpty (connect))
58InBlock.gif            throw new ProviderException
59InBlock.gif                ("Empty or missing connectionStringName");
60InBlock.gif
61InBlock.gif        config.Remove ("connectionStringName");
62InBlock.gif
63InBlock.gif        if (WebConfigurationManager.ConnectionStrings[connect] == null)
64InBlock.gif            throw new ProviderException ("Missing connection string");
65InBlock.gif
66InBlock.gif        _connectionString = WebConfigurationManager.ConnectionStrings
67InBlock.gif            [connect].ConnectionString;
68InBlock.gif
69InBlock.gif        if (String.IsNullOrEmpty (_connectionString))
70InBlock.gif            throw new ProviderException ("Empty connection string");
71InBlock.gif
72InBlock.gif        // Throw an exception if unrecognized attributes remain
73ExpandedSubBlockStart.gifContractedSubBlock.gif        if (config.Count > 0dot.gif{
74InBlock.gif            string attr = config.GetKey (0);
75InBlock.gif            if (!String.IsNullOrEmpty (attr))
76InBlock.gif                throw new ProviderException
77InBlock.gif                    ("Unrecognized attribute: " + attr);
78ExpandedSubBlockEnd.gif        }

79ExpandedSubBlockEnd.gif    }

80InBlock.gif
81InBlock.gif    public override Image RetrieveImage (string id)
82ExpandedSubBlockStart.gifContractedSubBlock.gif    dot.gif{
83InBlock.gif        // TODO: Retrieve an image from the database using
84InBlock.gif        // _connectionString to open a database connection
85ExpandedSubBlockEnd.gif    }

86InBlock.gif
87InBlock.gif    public override void SaveImage (string id, Image image)
88ExpandedSubBlockStart.gifContractedSubBlock.gif    dot.gif{
89InBlock.gif        throw new NotSupportedException ();
90ExpandedSubBlockEnd.gif    }

91ExpandedBlockEnd.gif}


配置基于Provider的自定义服务
现在可以看看如何在 Web.Config 中配置它所需的节点。这里在 <System.Web> 节中添加了 <ImageService> 节,在属性 defaultProvider 中指定了它使用的默认 Provider 服务。

3. Web.Config 文件中配置 Image Service

 1 None.gif < configuration  >
 2 None.gif   dot.gif
 3 None.gif   < connectionStrings >
 4 None.gif     < add  name ="ImageServiceConnectionString"  connectionString ="dot.gif"   />
 5 None.gif   </ connectionStrings >
 6 None.gif   < system .web >
 7 None.gif     < imageService  defaultProvider ="SqlImageProvider" >
 8 None.gif       < providers >
 9 None.gif         < add  name ="SqlImageProvider"  type ="SqlImageProvider"
10 None.gif          connectionStringName ="ImageServiceConnectionString" />
11 None.gif       </ providers >
12 None.gif     </ imageService >
13 None.gif   </ system.web >
14 None.gif </ configuration >

 

结构节点<ImageServer> 现在系统是不可识别的,所有必需还要有一个相应的类用来描述 <ImageServer> 配置节。

4. <imageServer> 配置节的描述类

 1 None.gif using System;
 2 None.gifusing System.Configuration;
 3 None.gif
 4 None.gifpublic class ImageServiceSection : ConfigurationSection
 5 None.gif{
 6 None.gif    [ConfigurationProperty("providers")]
 7 None.gif    public ProviderSettingsCollection Providers
 8 None.gif    {
 9 None.gif        get { return (ProviderSettingsCollection) base["providers"]; }
10 None.gif    }
11 None.gif
12 None.gif    [StringValidator(MinLength = 1)]
13 None.gif    [ConfigurationProperty("defaultProvider",
14 None.gif        DefaultValue = "SqlImageProvider")]
15 None.gif    public string DefaultProvider
16 None.gif    {
17 None.gif        get { return (string) base["defaultProvider"]; }
18 None.gif        set { base["defaultProvider"] = value; }
19 None.gif    }
20 None.gif}
21 None.gif
22 None.gif

这一下可以在 Web.Config 中注册 <imageService> 节了,并且它会被系统识别。

5. 创建 <imageService> 这个配置节的处理类

 

 1 None.gif < configuration  >
 2 None.gif   < configSections >
 3 None.gif     < sectionGroup  name ="system.web" >
 4 None.gif       < section  name ="imageService"
 5 None.gif        type ="ImageServiceSection, CustomSections"
 6 None.gif        allowDefinition ="MachineToApplication"
 7 None.gif        restartOnExternalChanges ="true"   />
 8 None.gif     </ sectionGroup >
 9 None.gif   </ configSections >
10 None.gif   < connectionStrings >
11 None.gif     < add  name ="ImageServiceConnectionString"  connectionString ="dot.gif"   />
12 None.gif   </ connectionStrings >
13 None.gif   < system .web >
14 None.gif     < imageService  defaultProvider ="SqlImageProvider" >
15 None.gif       < providers >
16 None.gif         < add  name ="SqlImageProvider"  type ="SqlImageProvider"
17 None.gif          connectionStringName ="ImageServiceConnectionString" />
18 None.gif       </ providers >
19 None.gif     </ imageService >
20 None.gif   </ system.web >
21 None.gif </ configuration >
22 None.gif
23 None.gif

现在可以加载并初始化自定义的 Providers
上面的事情都完成后,就可以实现这个 ImageService 了,它将根据 Web.Config 加载配置中默认的ImageProvider ,可以在 ImageService 类中直接使用它。

6、创建 ImageService 类,它将使用配置中的实例来处理

 

 1 None.gif using  System;
 2 None.gif using  System.Drawing;
 3 None.gif using  System.Configuration;
 4 None.gif using  System.Configuration.Provider;
 5 None.gif using  System.Web.Configuration;
 6 None.gif using  System.Web;
 7 None.gif
 8 None.gif public   class  ImageService
 9 ExpandedBlockStart.gifContractedBlock.gif dot.gif {
10InBlock.gif    private static ImageProvider _provider = null;
11InBlock.gif    private static ImageProviderCollection _providers = null;
12InBlock.gif    private static object _lock = new object();
13InBlock.gif    
14InBlock.gif    public ImageProvider Provider
15ExpandedSubBlockStart.gifContractedSubBlock.gif    dot.gif{
16ExpandedSubBlockStart.gifContractedSubBlock.gif        get dot.gifreturn _provider; }
17ExpandedSubBlockEnd.gif    }

18InBlock.gif
19InBlock.gif    public ImageProviderCollection Providers
20ExpandedSubBlockStart.gifContractedSubBlock.gif    dot.gif{
21ExpandedSubBlockStart.gifContractedSubBlock.gif        get dot.gifreturn _providers; }
22ExpandedSubBlockEnd.gif    }

23InBlock.gif
24InBlock.gif    public static Image RetrieveImage(int imageID)
25ExpandedSubBlockStart.gifContractedSubBlock.gif    dot.gif{
26InBlock.gif        // Make sure a provider is loaded
27InBlock.gif        LoadProviders();
28InBlock.gif
29InBlock.gif        // Delegate to the provider
30InBlock.gif        return _provider.RetrieveImage(imageID);
31ExpandedSubBlockEnd.gif    }

32InBlock.gif
33InBlock.gif    public static void SaveImage(Image image)
34ExpandedSubBlockStart.gifContractedSubBlock.gif    dot.gif{
35InBlock.gif        // Make sure a provider is loaded
36InBlock.gif        LoadProviders();
37InBlock.gif
38InBlock.gif        // Delegate to the provider
39InBlock.gif        _provider.SaveImage(image);
40ExpandedSubBlockEnd.gif    }

41InBlock.gif
42InBlock.gif    private static void LoadProviders()
43ExpandedSubBlockStart.gifContractedSubBlock.gif    dot.gif{
44InBlock.gif        // Avoid claiming lock if providers are already loaded
45InBlock.gif        if (_provider == null)
46ExpandedSubBlockStart.gifContractedSubBlock.gif        dot.gif{
47InBlock.gif            lock (_lock)
48ExpandedSubBlockStart.gifContractedSubBlock.gif            dot.gif{
49InBlock.gif                // Do this again to make sure _provider is still null
50InBlock.gif                if (_provider == null)
51ExpandedSubBlockStart.gifContractedSubBlock.gif                dot.gif{
52InBlock.gif                    // Get a reference to the <imageService> section
53InBlock.gif                    ImageServiceSection section = (ImageServiceSection)
54InBlock.gif                        WebConfigurationManager.GetSection
55InBlock.gif                        ("system.web/imageService");
56InBlock.gif
57InBlock.gif                    // Load registered providers and point _provider
58InBlock.gif                    // to the default provider
59InBlock.gif                    _providers = new ImageProviderCollection();
60InBlock.gif                    ProvidersHelper.InstantiateProviders
61InBlock.gif                        (section.Providers, _providers,
62InBlock.gif                        typeof(ImageProvider));
63InBlock.gif                    _provider = _providers[section.DefaultProvider];
64InBlock.gif
65InBlock.gif                    if (_provider == null)
66InBlock.gif                        throw new ProviderException
67InBlock.gif                            ("Unable to load default ImageProvider");
68ExpandedSubBlockEnd.gif                }

69ExpandedSubBlockEnd.gif            }

70ExpandedSubBlockEnd.gif        }

71ExpandedSubBlockEnd.gif    }

72ExpandedBlockEnd.gif}

73 None.gif
74 None.gif

这些在 Asp.NET 2.0 中被支持。

转载于:https://www.cnblogs.com/eos/archive/2006/10/09/524000.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值