我看到entlib4.0中说可以通过继承ICacheManager来实现自己的cachemanager,我就想着该如何把其他的缓存工具集成到这里面来,我使用的是indeXus.Net Shared Cache (http://www.codeplex.com/SharedCache)。
这个问题我搞了一晚上都没有明白,所以贴出来想请大家看看是什么原因。如果管理员觉得不适合放置在首页请移走,很抱歉。
我看到entlib4.0中说可以通过继承ICacheManager来实现自己的cachemanager,我就想着该如何把其他的缓存工具集成到这里面来,我使用的是indeXus.Net Shared Cache (http://www.codeplex.com/SharedCache)。
我看了帮助文档,上面写只要继承ICacheManager和使用[ConfigurationElementTypeAttribute(typeof(CustomCacheManagerData))]属性标签,所以我很快就写了一个自己的CacheManager (其中很多代码来自一篇codeplex上的帖子,他没有包含标签的使用,地址忘记了)
我看到entlib4.0中说可以通过继承ICacheManager来实现自己的cachemanager,我就想着该如何把其他的缓存工具集成到这里面来,我使用的是indeXus.Net Shared Cache (http://www.codeplex.com/SharedCache)。
我看了帮助文档,上面写只要继承ICacheManager和使用[ConfigurationElementTypeAttribute(typeof(CustomCacheManagerData))]属性标签,所以我很快就写了一个自己的CacheManager (其中很多代码来自一篇codeplex上的帖子,他没有包含标签的使用,地址忘记了)
Code
1using System;
2using System.Collections.Generic;
3using System.Linq;
4using System.Text;
5using System.Data;
6using System.Web;
7using System.IO;
8using Microsoft.Practices.EnterpriseLibrary.Caching;
9using Microsoft.Practices.EnterpriseLibrary.Caching.Expirations;
10using MergeSystem.Indexus.WinServiceCommon;
11using MergeSystem.Indexus;
12using MergeSystem.Indexus.WinServiceCommon.Provider.Cache;
13using Microsoft.Practices.EnterpriseLibrary.Common.Configuration;
14using Microsoft.Practices.EnterpriseLibrary.Caching.Configuration;
15
16namespace adow.shirecache.cachemanager
17{
18 /**//// <summary>
19 /// 继承自ICacheManager,实现Indexus的CacheManager封装
20 /// </summary>
21 [ConfigurationElementTypeAttribute(typeof(CustomCacheManagerData))]
22 //[ConfigurationElementType()]
23 public class ShireCacheManagerIndexus : ICacheManager, IDisposable
24 {
25 private Microsoft.Practices.EnterpriseLibrary.Caching.Cache realCache;
26 private BackgroundScheduler scheduler;
27 private ExpirationPollTimer pollTimer;
28
29 public ShireCacheManagerIndexus()
30 {
31
32 }
33 //public ShireCacheManagerIndexus(Microsoft.Practices.EnterpriseLibrary.Caching.Cache realCache,
34 // BackgroundScheduler scheduler, ExpirationPollTimer pollTimer)
35 //{
36 // this.realCache = realCache;
37 // this.scheduler = scheduler;
38 // this.pollTimer = pollTimer;
39 //}
40 public void Add(string key, object value,
41 CacheItemPriority scavengingPriority, ICacheItemRefreshAction refreshAction,
42 params ICacheItemExpiration[] expirations)
43 {
44 IndexusDistributionCache.SharedCache.Add(key, value, GetAbsoluteTimeExpiration(expirations),
45 GetCacheItemPriority(scavengingPriority));
46 //IndexusDistributionCache.SharedCache.Add(key, value);
47 }
48
49 public void Add(string key, object value)
50 {
51 IndexusDistributionCache.SharedCache.Add(key, value);
52
53 }
54
55 public bool Contains(string key)
56 {
57 IList<string> allkeys = IndexusDistributionCache.SharedCache.GetAllKeys();
58 if (allkeys != null)
59 return allkeys.Contains<string>(key);
60 else
61 return false;
62 }
63
64 public int Count
65 {
66 get
67 {
68 long total=IndexusDistributionCache.SharedCache.Count;
69 if (total > Int32.MaxValue)
70 throw new Exception("超出Int32最大值了");
71 else
72 return (int)total;
73 }
74 }
75
76 public void Flush()
77 {
78 IndexusDistributionCache.SharedCache.Clear();
79 }
80
81 public object GetData(string key)
82 {
83 return IndexusDistributionCache.SharedCache.Get(key);
84 }
85
86 public void Remove(string key)
87 {
88 IndexusDistributionCache.SharedCache.Remove(key);
89 }
90
91 public object this[string key]
92 {
93 get
94 {
95 return this.GetData(key);
96 }
97 }
98
99 /**//// <summary>
100 /// 将IndexusMessage.CacheItemPriority 转换到 Microsoft.Practices.EnterpriseLibrary.Caching.CacheItemPriority
101 /// </summary>
102 /// <param name="scavengingPriority"></param>
103 /// <returns></returns>
104 private static IndexusMessage.CacheItemPriority GetCacheItemPriority(CacheItemPriority scavengingPriority)
105 {
106 switch (scavengingPriority)
107 {
108 // TODO validate these mappings
109 case CacheItemPriority.NotRemovable: return IndexusMessage.CacheItemPriority.High;
110 case CacheItemPriority.High: return IndexusMessage.CacheItemPriority.AboveNormal;
111 case CacheItemPriority.Normal: return IndexusMessage.CacheItemPriority.Normal;
112 case CacheItemPriority.Low: return IndexusMessage.CacheItemPriority.BelowNormal;
113 case CacheItemPriority.None: return IndexusMessage.CacheItemPriority.Low;
114 }
115 return IndexusMessage.CacheItemPriority.Normal;
116 }
117 /**//// <summary>
118 /// 将enterprise libraray 的过期时间转换到 标准时间
119 /// 只能转换绝对时间
120 /// </summary>
121 /// <param name="expirations"></param>
122 /// <returns></returns>
123 private static DateTime GetAbsoluteTimeExpiration(ICacheItemExpiration[] expirations)
124 {
125 if (expirations != null)
126 {
127 foreach (ICacheItemExpiration expiration in expirations)
128 {
129 AbsoluteTime absoluteTimeExpiration = expiration as AbsoluteTime;
130 if (absoluteTimeExpiration != null)
131 return absoluteTimeExpiration.AbsoluteExpirationTime;
132 }
133 }
134 return DateTime.MinValue;
135 }
136
137 public void Dispose()
138 {
139 GC.SuppressFinalize(this);
140 }
141 }
142}
我对indexus的调用方法进行了测试,所以访问indexus的代码应该是正确的。
下面我将这个类配置到entlib cache中,配置文件:
Code
1<?xml version="1.0" encoding="utf-8" ?>
2<configuration>
3 <configSections>
4 <section name="cachingConfiguration"
5 type="Microsoft.Practices.EnterpriseLibrary.Caching.Configuration.CacheManagerSettings, Microsoft.Practices.EnterpriseLibrary.Caching, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" />
6 <!--indexus缓存-->
7 <section name="indexusNetSharedCache"
8 type="MergeSystem.Indexus.WinServiceCommon.Configuration.Client.IndexusProviderSection, MergeSystem.Indexus.WinServiceCommon"/>
9 </configSections>
10 <appSettings>
11 <add key="cache_root" value="E:\shirecachestore"/>
12 <add key="cache_write_key_table" value="1"/>
13 </appSettings>
14 <cachingConfiguration defaultCacheManager="SimpleCacheManager">
15 <cacheManagers>
16 <add expirationPollFrequencyInSeconds="60" maximumElementsInCacheBeforeScavenging="1000"
17 numberToRemoveWhenScavenging="10" backingStoreName="Null Storage"
18 type="Microsoft.Practices.EnterpriseLibrary.Caching.CacheManager, Microsoft.Practices.EnterpriseLibrary.Caching, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"
19 name="SimpleCacheManager" />
20 <add expirationPollFrequencyInSeconds="60" maximumElementsInCacheBeforeScavenging="1000"
21 numberToRemoveWhenScavenging="10" backingStoreName="Null Storage"
22 type="Microsoft.Practices.EnterpriseLibrary.Caching.CacheManager, Microsoft.Practices.EnterpriseLibrary.Caching, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"
23 name="LocalCacheManager" />
24 <!--使用indexus缓存管理器-->
25 <add type="adow.shirecache.cachemanager.ShireCacheManagerIndexus, adow.shirecache.cachemanager"
26 name="IndexusCacheManager" />
27 </cacheManagers>
28 <backingStores>
29 <add encryptionProviderName="" type="Microsoft.Practices.EnterpriseLibrary.Caching.BackingStoreImplementations.NullBackingStore, Microsoft.Practices.EnterpriseLibrary.Caching, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"
30 name="Null Storage" />
31 </backingStores>
32 </cachingConfiguration>
33 <!--indexus缓存-->
34 <indexusNetSharedCache defaultProvider="IndexusSharedCacheProvider">
35 <servers>
36 <add key="adow-cache-server" ipaddress="127.0.0.1" port="48888" />
37 </servers>
38 <providers>
39 <add
40 name="IndexusSharedCacheProvider"
41 type="MergeSystem.Indexus.WinServiceCommon.Provider.Cache.IndexusSharedCacheProvider, MergeSystem.Indexus.WinServiceCommon">
42 </add>
43 </providers>
44 </indexusNetSharedCache>
45</configuration>
我通过indexus的测试程序测试,确保indexus是在正确的运行中,下面开始使用cache,但是在构造对应的CacheManager时发生了错误,我们的常见的代码开始时这样:
Test method adow.shirecache.test.UnitTest1.TestGetCache threw exception: Microsoft.Practices.ObjectBuilder2.BuildFailedException: The current build operation (build key Build Key[Microsoft.Practices.EnterpriseLibrary.Caching.ICacheManager, IndexusCacheManager]) failed: 未找到类型“adow.shirecache.cachemanager.ShireCacheManagerIndexus”上的构造函数。 (Strategy type Microsoft.Practices.EnterpriseLibrary.Common.Configuration.ObjectBuilder.ConfiguredObjectStrategy, index 2) ---> System.MissingMethodException: 未找到类型“adow.shirecache.cachemanager.ShireCacheManagerIndexus”上的构造函数。
说没有构造函数,但是我明明写了一个不带参数的构造函数,(还复制了一个CacheManager的构造写法)。如果我使用默认的cachename是没有问题的。
然后我不使用CacheFactory,而是直接创建
manager = new adow.shirecache.cachemanager.ShireCacheManagerIndexus();
是正常的,后面的操作也没有问题。
我用unity的方式来构造也没有问题:
1using System;
2using System.Collections.Generic;
3using System.Linq;
4using System.Text;
5using System.Data;
6using System.Web;
7using System.IO;
8using Microsoft.Practices.EnterpriseLibrary.Caching;
9using Microsoft.Practices.EnterpriseLibrary.Caching.Expirations;
10using MergeSystem.Indexus.WinServiceCommon;
11using MergeSystem.Indexus;
12using MergeSystem.Indexus.WinServiceCommon.Provider.Cache;
13using Microsoft.Practices.EnterpriseLibrary.Common.Configuration;
14using Microsoft.Practices.EnterpriseLibrary.Caching.Configuration;
15
16namespace adow.shirecache.cachemanager
17{
18 /**//// <summary>
19 /// 继承自ICacheManager,实现Indexus的CacheManager封装
20 /// </summary>
21 [ConfigurationElementTypeAttribute(typeof(CustomCacheManagerData))]
22 //[ConfigurationElementType()]
23 public class ShireCacheManagerIndexus : ICacheManager, IDisposable
24 {
25 private Microsoft.Practices.EnterpriseLibrary.Caching.Cache realCache;
26 private BackgroundScheduler scheduler;
27 private ExpirationPollTimer pollTimer;
28
29 public ShireCacheManagerIndexus()
30 {
31
32 }
33 //public ShireCacheManagerIndexus(Microsoft.Practices.EnterpriseLibrary.Caching.Cache realCache,
34 // BackgroundScheduler scheduler, ExpirationPollTimer pollTimer)
35 //{
36 // this.realCache = realCache;
37 // this.scheduler = scheduler;
38 // this.pollTimer = pollTimer;
39 //}
40 public void Add(string key, object value,
41 CacheItemPriority scavengingPriority, ICacheItemRefreshAction refreshAction,
42 params ICacheItemExpiration[] expirations)
43 {
44 IndexusDistributionCache.SharedCache.Add(key, value, GetAbsoluteTimeExpiration(expirations),
45 GetCacheItemPriority(scavengingPriority));
46 //IndexusDistributionCache.SharedCache.Add(key, value);
47 }
48
49 public void Add(string key, object value)
50 {
51 IndexusDistributionCache.SharedCache.Add(key, value);
52
53 }
54
55 public bool Contains(string key)
56 {
57 IList<string> allkeys = IndexusDistributionCache.SharedCache.GetAllKeys();
58 if (allkeys != null)
59 return allkeys.Contains<string>(key);
60 else
61 return false;
62 }
63
64 public int Count
65 {
66 get
67 {
68 long total=IndexusDistributionCache.SharedCache.Count;
69 if (total > Int32.MaxValue)
70 throw new Exception("超出Int32最大值了");
71 else
72 return (int)total;
73 }
74 }
75
76 public void Flush()
77 {
78 IndexusDistributionCache.SharedCache.Clear();
79 }
80
81 public object GetData(string key)
82 {
83 return IndexusDistributionCache.SharedCache.Get(key);
84 }
85
86 public void Remove(string key)
87 {
88 IndexusDistributionCache.SharedCache.Remove(key);
89 }
90
91 public object this[string key]
92 {
93 get
94 {
95 return this.GetData(key);
96 }
97 }
98
99 /**//// <summary>
100 /// 将IndexusMessage.CacheItemPriority 转换到 Microsoft.Practices.EnterpriseLibrary.Caching.CacheItemPriority
101 /// </summary>
102 /// <param name="scavengingPriority"></param>
103 /// <returns></returns>
104 private static IndexusMessage.CacheItemPriority GetCacheItemPriority(CacheItemPriority scavengingPriority)
105 {
106 switch (scavengingPriority)
107 {
108 // TODO validate these mappings
109 case CacheItemPriority.NotRemovable: return IndexusMessage.CacheItemPriority.High;
110 case CacheItemPriority.High: return IndexusMessage.CacheItemPriority.AboveNormal;
111 case CacheItemPriority.Normal: return IndexusMessage.CacheItemPriority.Normal;
112 case CacheItemPriority.Low: return IndexusMessage.CacheItemPriority.BelowNormal;
113 case CacheItemPriority.None: return IndexusMessage.CacheItemPriority.Low;
114 }
115 return IndexusMessage.CacheItemPriority.Normal;
116 }
117 /**//// <summary>
118 /// 将enterprise libraray 的过期时间转换到 标准时间
119 /// 只能转换绝对时间
120 /// </summary>
121 /// <param name="expirations"></param>
122 /// <returns></returns>
123 private static DateTime GetAbsoluteTimeExpiration(ICacheItemExpiration[] expirations)
124 {
125 if (expirations != null)
126 {
127 foreach (ICacheItemExpiration expiration in expirations)
128 {
129 AbsoluteTime absoluteTimeExpiration = expiration as AbsoluteTime;
130 if (absoluteTimeExpiration != null)
131 return absoluteTimeExpiration.AbsoluteExpirationTime;
132 }
133 }
134 return DateTime.MinValue;
135 }
136
137 public void Dispose()
138 {
139 GC.SuppressFinalize(this);
140 }
141 }
142}
我对indexus的调用方法进行了测试,所以访问indexus的代码应该是正确的。
下面我将这个类配置到entlib cache中,配置文件:
Code
1<?xml version="1.0" encoding="utf-8" ?>
2<configuration>
3 <configSections>
4 <section name="cachingConfiguration"
5 type="Microsoft.Practices.EnterpriseLibrary.Caching.Configuration.CacheManagerSettings, Microsoft.Practices.EnterpriseLibrary.Caching, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" />
6 <!--indexus缓存-->
7 <section name="indexusNetSharedCache"
8 type="MergeSystem.Indexus.WinServiceCommon.Configuration.Client.IndexusProviderSection, MergeSystem.Indexus.WinServiceCommon"/>
9 </configSections>
10 <appSettings>
11 <add key="cache_root" value="E:\shirecachestore"/>
12 <add key="cache_write_key_table" value="1"/>
13 </appSettings>
14 <cachingConfiguration defaultCacheManager="SimpleCacheManager">
15 <cacheManagers>
16 <add expirationPollFrequencyInSeconds="60" maximumElementsInCacheBeforeScavenging="1000"
17 numberToRemoveWhenScavenging="10" backingStoreName="Null Storage"
18 type="Microsoft.Practices.EnterpriseLibrary.Caching.CacheManager, Microsoft.Practices.EnterpriseLibrary.Caching, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"
19 name="SimpleCacheManager" />
20 <add expirationPollFrequencyInSeconds="60" maximumElementsInCacheBeforeScavenging="1000"
21 numberToRemoveWhenScavenging="10" backingStoreName="Null Storage"
22 type="Microsoft.Practices.EnterpriseLibrary.Caching.CacheManager, Microsoft.Practices.EnterpriseLibrary.Caching, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"
23 name="LocalCacheManager" />
24 <!--使用indexus缓存管理器-->
25 <add type="adow.shirecache.cachemanager.ShireCacheManagerIndexus, adow.shirecache.cachemanager"
26 name="IndexusCacheManager" />
27 </cacheManagers>
28 <backingStores>
29 <add encryptionProviderName="" type="Microsoft.Practices.EnterpriseLibrary.Caching.BackingStoreImplementations.NullBackingStore, Microsoft.Practices.EnterpriseLibrary.Caching, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"
30 name="Null Storage" />
31 </backingStores>
32 </cachingConfiguration>
33 <!--indexus缓存-->
34 <indexusNetSharedCache defaultProvider="IndexusSharedCacheProvider">
35 <servers>
36 <add key="adow-cache-server" ipaddress="127.0.0.1" port="48888" />
37 </servers>
38 <providers>
39 <add
40 name="IndexusSharedCacheProvider"
41 type="MergeSystem.Indexus.WinServiceCommon.Provider.Cache.IndexusSharedCacheProvider, MergeSystem.Indexus.WinServiceCommon">
42 </add>
43 </providers>
44 </indexusNetSharedCache>
45</configuration>
我通过indexus的测试程序测试,确保indexus是在正确的运行中,下面开始使用cache,但是在构造对应的CacheManager时发生了错误,我们的常见的代码开始时这样:
Code
ICacheManager manager = null;
if (cachename != null && !cachename.Equals(""))
{
manager = CacheFactory.GetCacheManager(cachename);
}
else
{
manager = CacheFactory.GetCacheManager();
}
这时遇到了一个异常:ICacheManager manager = null;
if (cachename != null && !cachename.Equals(""))
{
manager = CacheFactory.GetCacheManager(cachename);
}
else
{
manager = CacheFactory.GetCacheManager();
}
Test method adow.shirecache.test.UnitTest1.TestGetCache threw exception: Microsoft.Practices.ObjectBuilder2.BuildFailedException: The current build operation (build key Build Key[Microsoft.Practices.EnterpriseLibrary.Caching.ICacheManager, IndexusCacheManager]) failed: 未找到类型“adow.shirecache.cachemanager.ShireCacheManagerIndexus”上的构造函数。 (Strategy type Microsoft.Practices.EnterpriseLibrary.Common.Configuration.ObjectBuilder.ConfiguredObjectStrategy, index 2) ---> System.MissingMethodException: 未找到类型“adow.shirecache.cachemanager.ShireCacheManagerIndexus”上的构造函数。
说没有构造函数,但是我明明写了一个不带参数的构造函数,(还复制了一个CacheManager的构造写法)。如果我使用默认的cachename是没有问题的。
然后我不使用CacheFactory,而是直接创建
manager = new adow.shirecache.cachemanager.ShireCacheManagerIndexus();
是正常的,后面的操作也没有问题。
我用unity的方式来构造也没有问题:
Code
1IUnityContainer container = new UnityContainer();
2container.RegisterType<ICacheManager,ShireCacheManagerIndexus>("indexus");
3manager = container.Resolve<ICacheManager>("indexus");
问题是后两种都忽略了配置文件的存在,手工来创建cachemanager,没有实际意义。
然而,为什么我在使用cachefactory时却出现了“没有找到构造函数”呢,是我的cachemanager有问题呢,还是我在配置文件中的写法有问题呢?
1IUnityContainer container = new UnityContainer();
2container.RegisterType<ICacheManager,ShireCacheManagerIndexus>("indexus");
3manager = container.Resolve<ICacheManager>("indexus");
问题是后两种都忽略了配置文件的存在,手工来创建cachemanager,没有实际意义。
然而,为什么我在使用cachefactory时却出现了“没有找到构造函数”呢,是我的cachemanager有问题呢,还是我在配置文件中的写法有问题呢?