存储与对象关联的某些元数据的正确方法?

时间:2018-11-21 02:35:54

标签: c# caching memory-leaks metadata

首先,我担心这里的内存泄漏问题。因为我要做的是使用一些词典来存储带有对象本身键的元数据。因此,我可以通过传入对象来查找元数据(应该是动态的)。

请注意,此处的对象没有任何GUID来帮助标识自己,唯一的标识方法是通过其实例。 这种存储看起来很像WPF中DependencyObject中的存储。我们可以声明DependencyProperty(附加属性)以扩展DependencyObject(元数据包含在附加属性中)。

这是我所拥有的:

Dictionary<object, SomeMetaData> _metadataLookup = new Dictionary<object,SomeMetaData>();
//to store metadata
_metadataLookup[someObject] = someMetaData;
//to get metadata
SomeMetaData someMetaData;
_metadataLookup.TryGetValue(someObject, out someMetaData);

如果someObject的生存期与使用_metadataLookup的作用域的生存期相同,那就很好了。但是,如果someObject(存储在_metadataLookup之后)应该被销毁(逻辑上未使用)怎么办?我们还必须从_metadataLookup中手动将其删除,否则那里会发生内存泄漏。

我正在寻找一个更好的解决方案,出乎意料的是忘记手动删除对象,或者根本不知道何时应该删除对象是一个问题。谢谢。

1 个答案:

答案 0 :(得分:7)

为此,您可以使用ConditionalWeakTable

public class Example
{
   public static void Main()
   {
      var mc1 = new ManagedClass();
      var mc2 = new ManagedClass();
      var mc3 = new ManagedClass();

      var cwt = new ConditionalWeakTable<ManagedClass, ClassData>();
      cwt.Add(mc1, new ClassData());          
      cwt.Add(mc2, new ClassData());
      cwt.Add(mc3, new ClassData());

      var wr2 = new WeakReference(mc2);
      mc2 = null;

      GC.Collect();

      ClassData data = null; 

      if (wr2.Target == null)
          Console.WriteLine("No strong reference to mc2 exists.");   
      else if (cwt.TryGetValue(mc2, out data))
          Console.WriteLine("Data created at {0}", data.CreationTime);      
      else
          Console.WriteLine("mc2 not found in the table.");
   }
}

public class ManagedClass
{ 
}

public class ClassData
{
   public DateTime CreationTime;
   public object Data;   

   public ClassData()
   {
      CreationTime = DateTime.Now;
      this.Data  = new object();     
   }
}
// The example displays the following output:
//       No strong reference to mc2 exists.