我看到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

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17



18


19

20

21

22

23

24



25

26

27

28

29

30



31

32

33

34

35

36

37

38

39

40

41

42

43



44

45

46

47

48

49

50



51

52

53

54

55

56



57

58

59

60

61

62

63

64

65



66

67



68

69

70

71

72

73

74

75

76

77



78

79

80

81

82



83

84

85

86

87



88

89

90

91

92



93

94



95

96

97

98

99


100

101

102

103

104

105



106

107



108

109

110

111

112

113

114

115

116

117


118

119

120

121

122

123

124



125

126



127

128



129

130

131

132

133

134

135

136

137

138



139

140

141

142

我对indexus的调用方法进行了测试,所以访问indexus的代码应该是正确的。
下面我将这个类配置到entlib cache中,配置文件:


1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

我通过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

2

3

问题是后两种都忽略了配置文件的存在,手工来创建cachemanager,没有实际意义。
然而,为什么我在使用cachefactory时却出现了“没有找到构造函数”呢,是我的cachemanager有问题呢,还是我在配置文件中的写法有问题呢?