forked from SharpRepository/SharpRepository
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathCacheRepositoryBase.cs
More file actions
148 lines (120 loc) · 4.5 KB
/
CacheRepositoryBase.cs
File metadata and controls
148 lines (120 loc) · 4.5 KB
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
143
144
145
146
147
148
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq;
using SharpRepository.Repository;
using SharpRepository.Repository.Caching;
using SharpRepository.Repository.FetchStrategies;
using System.Reflection;
namespace SharpRepository.CacheRepository
{
public abstract class CacheRepositoryBase<T, TKey> : LinqRepositoryBase<T, TKey> where T : class, new()
{
private readonly string _prefix;
private readonly ICachingProvider _cachingProvider;
internal CacheRepositoryBase(string prefix, ICachingProvider cachingProvider, ICachingStrategy<T, TKey> cachingStrategy = null)
: base(cachingStrategy)
{
_prefix = prefix;
_cachingProvider = cachingProvider;
}
private ConcurrentDictionary<TKey, T> Items
{
get
{
ConcurrentDictionary<TKey, T> items = null;
if (!_cachingProvider.Exists(_prefix + ".CacheRepository.Items"))
{
items = new ConcurrentDictionary<TKey, T>();
_cachingProvider.Set(_prefix + ".CacheRepository.Items", items);
}
else
{
if (!_cachingProvider.Get(_prefix + ".CacheRepository.Items", out items))
{
items = new ConcurrentDictionary<TKey, T>();
}
}
return items;
}
set
{
_cachingProvider.Set(_prefix + ".CacheRepository.Items", value);
}
}
protected override IQueryable<T> BaseQuery(IFetchStrategy<T> fetchStrategy = null)
{
return CloneDictionary(Items).AsQueryable();
}
protected override T GetQuery(TKey key, IFetchStrategy<T> fetchStrategy)
{
Items.TryGetValue(key, out T result);
return result;
}
private static IEnumerable<T> CloneDictionary(ConcurrentDictionary<TKey, T> list)
{
// when you Google deep copy of generic list every answer uses either the IClonable interface on the T or having the T be Serializable
// since we can't really put those constraints on T I'm going to do it via reflection
var type = typeof(T);
var properties = type.GetTypeInfo().DeclaredProperties;
var clonedList = new List<T>(list.Count);
foreach (var keyValuePair in list)
{
var newItem = new T();
foreach (var propInfo in properties)
{
propInfo.SetValue(newItem, propInfo.GetValue(keyValuePair.Value, null), null);
}
clonedList.Add(newItem);
}
return clonedList;
}
protected override void AddItem(T entity)
{
if (GetPrimaryKey(entity, out TKey id) && GenerateKeyOnAdd && Equals(id, default(TKey)))
{
id = GeneratePrimaryKey();
SetPrimaryKey(entity, id);
}
Items[id] = entity;
}
protected override void DeleteItem(T entity)
{
GetPrimaryKey(entity, out TKey pkValue);
Items.TryRemove(pkValue, out T tmp);
}
protected override void UpdateItem(T entity)
{
GetPrimaryKey(entity, out TKey pkValue);
Items[pkValue] = entity;
}
protected override void SaveChanges()
{
}
public override void Dispose()
{
}
protected virtual TKey GeneratePrimaryKey()
{
if (typeof(TKey) == typeof(Guid))
{
return (TKey)Convert.ChangeType(Guid.NewGuid(), typeof(TKey));
}
if (typeof(TKey) == typeof(string))
{
return (TKey)Convert.ChangeType(Guid.NewGuid().ToString("N"), typeof(TKey));
}
if (typeof(TKey) == typeof(Int32))
{
var pkValue = Items.Keys.LastOrDefault();
var nextInt = Convert.ToInt32(pkValue) + 1;
return (TKey)Convert.ChangeType(nextInt, typeof(TKey));
}
throw new InvalidOperationException("Primary key could not be generated. This only works for GUID, Int32 and String.");
}
public override string ToString()
{
return "SharpRepository.CacheRepository";
}
}
}