我看到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上的帖子,他没有包含标签的使用,地址忘记了)

Code
1
using System;
2
using System.Collections.Generic;
3
using System.Linq;
4
using System.Text;
5
using System.Data;
6
using System.Web;
7
using System.IO;
8
using Microsoft.Practices.EnterpriseLibrary.Caching;
9
using Microsoft.Practices.EnterpriseLibrary.Caching.Expirations;
10
using MergeSystem.Indexus.WinServiceCommon;
11
using MergeSystem.Indexus;
12
using MergeSystem.Indexus.WinServiceCommon.Provider.Cache;
13
using Microsoft.Practices.EnterpriseLibrary.Common.Configuration;
14
using Microsoft.Practices.EnterpriseLibrary.Caching.Configuration;
15
16
namespace 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();
}
这时遇到了一个异常:
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
1
IUnityContainer container = new UnityContainer();
2
container.RegisterType<ICacheManager,ShireCacheManagerIndexus>("indexus");
3
manager = container.Resolve<ICacheManager>("indexus");
问题是后两种都忽略了配置文件的存在,手工来创建cachemanager,没有实际意义。
然而,为什么我在使用cachefactory时却出现了“没有找到构造函数”呢,是我的cachemanager有问题呢,还是我在配置文件中的写法有问题呢?
我看到entlib4.0中说可以通过继承ICacheManager来实现自己的cachemanager,我就想着该如何把其他的缓存工具集成到这里面来,我使用的是indeXus.Net Shared Cache (http://www.codeplex.com/SharedCache)。
我看了帮助文档,上面写只要继承ICacheManager和使用[ConfigurationElementTypeAttribute(typeof(CustomCacheManagerData))]属性标签,所以我很快就写了一个自己的CacheManager (其中很多代码来自一篇codeplex上的帖子,他没有包含标签的使用,地址忘记了)
1
using System;2
using System.Collections.Generic;3
using System.Linq;4
using System.Text;5
using System.Data;6
using System.Web;7
using System.IO;8
using Microsoft.Practices.EnterpriseLibrary.Caching;9
using Microsoft.Practices.EnterpriseLibrary.Caching.Expirations;10
using MergeSystem.Indexus.WinServiceCommon;11
using MergeSystem.Indexus;12
using MergeSystem.Indexus.WinServiceCommon.Provider.Cache;13
using Microsoft.Practices.EnterpriseLibrary.Common.Configuration;14
using Microsoft.Practices.EnterpriseLibrary.Caching.Configuration;15

16
namespace adow.shirecache.cachemanager17


{18

/**//// <summary>19
/// 继承自ICacheManager,实现Indexus的CacheManager封装20
/// </summary>21
[ConfigurationElementTypeAttribute(typeof(CustomCacheManagerData))]22
//[ConfigurationElementType()]23
public class ShireCacheManagerIndexus : ICacheManager, IDisposable24

{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
else61
return false;62
}63

64
public int Count65

{66
get67

{68
long total=IndexusDistributionCache.SharedCache.Count;69
if (total > Int32.MaxValue)70
throw new Exception("超出Int32最大值了");71
else72
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
get94

{95
return this.GetData(key);96
}97
}98

99

/**//// <summary>100
/// 将IndexusMessage.CacheItemPriority 转换到 Microsoft.Practices.EnterpriseLibrary.Caching.CacheItemPriority101
/// </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 mappings109
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中,配置文件:
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
<add40
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时发生了错误,我们的常见的代码开始时这样:
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的方式来构造也没有问题:
1
IUnityContainer container = new UnityContainer();2
container.RegisterType<ICacheManager,ShireCacheManagerIndexus>("indexus");3
manager = container.Resolve<ICacheManager>("indexus");问题是后两种都忽略了配置文件的存在,手工来创建cachemanager,没有实际意义。
然而,为什么我在使用cachefactory时却出现了“没有找到构造函数”呢,是我的cachemanager有问题呢,还是我在配置文件中的写法有问题呢?
浙公网安备 33010602011771号