-
Notifications
You must be signed in to change notification settings - Fork 0
/
ResourceRepository.cs
112 lines (97 loc) · 2.27 KB
/
ResourceRepository.cs
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
using System;
using System.Collections.Generic;
using System.Threading;
using System.IO;
namespace netzlib
{
internal interface IResourceRepository
{
void Add(Uri resource);
void Add(string resource);
void Add(uint key, uint[] resources, ContentFilter filter);
string GetContent(uint key);
}
internal delegate string ContentFilter(string content);
internal class ResourceRepository : IResourceRepository
{
readonly ReaderWriterLockSlim locks = new ReaderWriterLockSlim();
readonly Dictionary<uint, Resource> resources = new Dictionary<uint, Resource>();
readonly ExternalResourceFetcher fetcher = new ExternalResourceFetcher();
public void Add(Uri resourceUri)
{
var key = resourceUri.GetKey();
AddInternal(key, () =>
{
FileInfo file;
ExternalResource resource;
if (resourceUri.TryMapPath(out file))
{
resource = new ExternalResource { Uri = new Uri(file.FullName) };
}
else
{
resource = new ExternalResource { Uri = resourceUri };
}
resources.Add(key, resource);
fetcher.Fetch(resource);
});
}
public void Add(string content)
{
var key = content.GetKey();
AddInternal(key, () => resources.Add(key, new Resource { Content = content }));
}
public void Add(uint key, uint[] resourceList, ContentFilter filter)
{
AddInternal(key, () =>
{
var l = new List<Resource>();
foreach (var resourceKey in resourceList)
{
if (!resources.ContainsKey(resourceKey))
{
throw new InvalidOperationException(
"members of composite resources must be added to the repository first");
}
l.Add(resources[resourceKey]);
}
resources.Add(key, new CompositeResource { Resources = l.ToArray(), Filter = filter });
});
}
public void AddInternal(uint key, Action add)
{
locks.EnterUpgradeableReadLock();
try
{
if (!resources.ContainsKey(key))
{
locks.EnterWriteLock();
try
{
add();
}
finally
{
locks.ExitWriteLock();
}
}
}
finally
{
locks.ExitUpgradeableReadLock();
}
}
public string GetContent(uint key)
{
locks.EnterReadLock();
try
{
return resources.ContainsKey(key) ? resources[key].Content : null;
}
finally
{
locks.ExitReadLock();
}
}
}
}