使用工厂类中的字典进行缓存 [英] Caching using dictionaries in a factory class

查看:95
本文介绍了使用工厂类中的字典进行缓存的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在WPF应用程序中,我正在使用第三方库来提取要允许用户与之交互的对象.

对象作为接口类型返回,并且我为它们创建了包装器类.我还创建了一个Factory类来实例化包装器类. 在工厂类内部,我使用字典针对每种不同的包装器类型来缓存包装器对象.

使用字典来缓存这些包装对象是一种好方法吗?这里有什么明显的问题吗?

public interface ICustomer // 3rd party Interface
{
    string Name {get; }
    string Address {get }

    // etc
}

public class ClientCustomer : IClientCustomer // Wrapper class
{
     ICustomer customer;
     public ClientCustomer(ICustomer cust)
     {
       this.customer = cust;
     }

     public string Name
     {
        get
        {
           return customer.Name;
        }
     }

    // etc
}

public class VmFactory
{
   private Dictionary<int, IClientCustomer> clientCustomers = 
        new Dictionary<int, IClientCustomer>();

    public IClientCustomer GetCustomerWrapper(ICustomer cust)
    {
       IClientCustomer clientCustomer;

       if (!clientCustomers.ContainsKey(cust.ID))
        {
            clientCustomer = new ClientCustomer(cust);
            clientCustomers.Add(cust.ID, clientCustomer);
        }
        else
        {
            clientCustomer = clientCustomers[cust.ID];
        }

          return clientCustomer;
   }

}

预先感谢

解决方案

首先,是的,您可以使用Dictionary进行缓存,但是您需要考虑线程安全性,缓存过期,无效等.

就像@Coastpear已经指出的那样,您使用它的方式不好,因为您的Dictionary被声明为实例变量.它需要具有静态实例,以便在工厂的多个实例之间进行缓存.如果您的应用程序是多线程的,则还需要同步对其的访问,以确保线程安全.注意:如果您在应用的生命周期内只有一个工厂实例,则Dictionary不必是静态的,但是如果要从多个线程访问它,则仍然需要同步对其的访问.

因此,我建议您使用 ConcurrentDictionary .对字典的访问本质上是线程安全的(您只需要担心其内容)

public class VmFactory
{
   private static ConcurrentDictionary<int, IClientCustomer> clientCustomers = 
        new ConcurrentDictionary<int, IClientCustomer>();

    public IClientCustomer GetCustomerWrapper(ICustomer cust)
    {
       IClientCustomer clientCustomer;

       if (!clientCustomers.ContainsKey(cust.ID))
        {
            clientCustomer = new ClientCustomer(cust);
            clientCustomers.TryAdd(cust.ID, clientCustomer);
        }
        else
        {
            clientCustomer = clientCustomers[cust.ID];
        }

          return clientCustomer;
   }
}

还可以查看 MemoryCache 作为另一种选择,尽管我认为ConcurrentDictionary足以满足您的情况.

In my WPF application, I'm using a third party library to fetch objects which I want to allow the user to interact with.

The objects are returned as interface types and I have created wrapper classes for them. I've also created a Factory class to instantiate the wrapper classes. Inside the factory class, I am caching the wrapper objects using dictionaries for each of the different wrapper types.

Is the use of the dictionary for caching these wrapper objects a good approach to take? Are there any obvious problems here?

public interface ICustomer // 3rd party Interface
{
    string Name {get; }
    string Address {get }

    // etc
}

public class ClientCustomer : IClientCustomer // Wrapper class
{
     ICustomer customer;
     public ClientCustomer(ICustomer cust)
     {
       this.customer = cust;
     }

     public string Name
     {
        get
        {
           return customer.Name;
        }
     }

    // etc
}

public class VmFactory
{
   private Dictionary<int, IClientCustomer> clientCustomers = 
        new Dictionary<int, IClientCustomer>();

    public IClientCustomer GetCustomerWrapper(ICustomer cust)
    {
       IClientCustomer clientCustomer;

       if (!clientCustomers.ContainsKey(cust.ID))
        {
            clientCustomer = new ClientCustomer(cust);
            clientCustomers.Add(cust.ID, clientCustomer);
        }
        else
        {
            clientCustomer = clientCustomers[cust.ID];
        }

          return clientCustomer;
   }

}

Thanks in advance

解决方案

First of all, yes you can use a Dictionary for caching but you need to consider thread safety, cache expiration, invalidation etc. I will propose alternate solutions further down.

Like @Coastpear has already pointed out, the way you're using it is no good as your Dictionary is declared as an instance variable. It needs to have a static instance in order to cache across multiple instances of the factory. If you're application is multithreaded, you'll also need to synchronize access to it in order to be thread-safe. Note: if you only have one instance of your factory for the lifetime of you app, the Dictionary don't have to be static, but you would still need to synchronize access to it if you're accessing it from multiple threads.

So, rather than using a Dictionary, I would suggest using a ConcurrentDictionary. Access to the dictionary is inherently thread-safe (you'll only have to worry about its contents)

public class VmFactory
{
   private static ConcurrentDictionary<int, IClientCustomer> clientCustomers = 
        new ConcurrentDictionary<int, IClientCustomer>();

    public IClientCustomer GetCustomerWrapper(ICustomer cust)
    {
       IClientCustomer clientCustomer;

       if (!clientCustomers.ContainsKey(cust.ID))
        {
            clientCustomer = new ClientCustomer(cust);
            clientCustomers.TryAdd(cust.ID, clientCustomer);
        }
        else
        {
            clientCustomer = clientCustomers[cust.ID];
        }

          return clientCustomer;
   }
}

Also have a look at MemoryCache as another alternative, although I think ConcurrentDictionary would suffice for your scenario.

这篇关于使用工厂类中的字典进行缓存的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆