我正在尝试为对象创建缓存机制。而我将创建一种工厂方法来创建对象并在字典中跟踪现有对象。所以,如果一个对象存在于字典中,我可以简单地返回它。如果该对象不存在,那么我可以实例化一个,将其添加到字典中,然后返回它。
基本上,我正在创建一个单身人士字典,可以这么说。我显然可以尝试坚持为每种类型创建单例,然后创建一个字典。我想知道是否有更好的方法来解决它,因为我目前的单身人士字典计划并不是那么有效。
答案 0 :(得分:1)
我给你一个想法,你可以使用各种各样的添加或删除该类的部分: 您缓存了一些对象(如果您需要,该数量可能会受到限制
容量)
最好使用2种结构:
LinledList和Dictionary(检索成本O(1))
您将缓存的对象保留在Dictionary中,当您需要再添加一个对象时,将其添加到Dictionary和LinkedList的末尾,当您获得最大容量时,您将从LinkedList中删除第一个对象,并从中删除相同的对象。字典能够添加一个新的。当您想要使用某个对象时,只需将其返回并将其在LinkedList中移动到最后。
因此,您可以在Dictionary中跟踪现有对象而不重复,并且您在LinkedList中获得缓存对象的“队列”,其中LinkedList的末尾是最后使用的对象。您可以根据需要实例化对象 - 为简单起见,我使用Item构造函数进行实例化。
public class Item
{
public string key;
public object obj;
public Item(string k, object o) { k = key; o = obj; }
}
class MyCache
{
LinkedList<Item> ll = new LinkedList<Item>();
LinkedListNode<Item> node;
Dictionary<string, LinkedListNode<Item>> dd = new Dictionary<string, LinkedListNode<Item>>();
int capacity = 5; //just for simplicity set capacity for caching
//here you Add new object
public void Add(string key, object obj)
{
if (cap == 0) return;
//check if you already have that object
if (!dd.TryGetValue(key, out node))
{
//if capacity exceeded- remove object from beginig of LinkedList
if (dd.Count >= capacity)
RemoveItem();
Item item = new Item(key, obj);
LinkedListNode<Item> newNode = new LinkedListNode<Item>(item);
ll.AddLast(newNode);
dd.Add(key, newNode);
return;
}
//we move that object to the end of the list
ll.Remove(node);
ll.AddLast(node);
}
// remove object from LinkedList and Dictionary
void RemoveItem()
{
LinkedListNode<Item> node = ll.First;
ll.Remove(node);
dd.Remove(node.Value.key);
}
public object Get(string key)
{
//if we have that object, we return it and move to the end of LList
if (dd.TryGetValue(key, out node))
{
ll.Remove(node);
ll.AddLast(node);
return node.Value.obj;
}
else return default(object);
}
}
答案 1 :(得分:0)
这是我自己使用的可靠缓存解决方案。主要想法很简单。 利用拦截器是一种有效的解决方案。拦截器将决定从缓存中检索数据或进行服务调用。 解决方案由三个不同的部分组成。第一部分是一个高度封装的存储库,它至少有四种主要的通用方法,用于注入,获取和消除(全部或特定)。如您所见,代码保证存储库中不存在冗余对象。
简单存储库
public static class Repository
{
private static Dictionary<Type, object> _dictionary;
static Repository()
{
_dictionary=new Dictionary<Type, object>();
}
public static T ReadRepository<T>()
{
var type = typeof (T);
object item;
var result = _dictionary.TryGetValue(type, out item);
if (!result) return default (T);
return (T)Convert.ChangeType(item, typeof(T));
}
public static void InjectRepository<T>(object value)
{
var type = typeof(T);
object item;
var result = _dictionary.TryGetValue(type, out item);
if(result)return;
_dictionary.Add(type, value);
}
}
在第二部分中,您需要创建一个名为[Cache]
的自定义属性。您的逻辑方法需要使用此属性进行修饰。例如,您有一个fetch方法,它进行服务调用以实现所需的数据。使用此属性,Interceptor将决定从缓存中检索信息或让方法进行服务调用。
逻辑方法
[Cache]
public User FetchUser(string userId)
{
//...
}
突出的一点是,您不能直接调用逻辑方法。拦截器将完成这一部分。实现可以利用的拦截器有不同的机制和模式。看下面的代码。使用委托理念,我已经成为了自己的执行者。
public delegate User UserDelegation(string userID);
一个简单的拦截器
public static object Executor(UserDelegation delegation)
{
// If it is decorated witch [Cache] attribute, Fetch data from cache
// Else
delegation.Invoke(userId);
//...
}