您的位置:首页 > 产品设计 > UI/UE

ConditionalWeakTable<TKey, TValue>使编译器可以将对象字段动态附加到托管对象。

2015-08-13 00:23 721 查看
MSDN关于它的介绍:https://msdn.microsoft.com/zh-cn/library/dd287757(v=vs.100).aspx

先看一个小demo:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
 
using System.Runtime.CompilerServices;
 
namespace ExtensionProps
{
    public class Person
    {
 
    }

    public class SomeClass
    {
 
    }

    public class ExtraPersonProps
    {
        public int Age { get; private set; }
        public string Name { get; private set; }
 

        public ExtraPersonProps(int age, string name)
        {
            Age = age;
            Name = name;
        }
    }
 
    class Program
    {
        static void Main(string[] args)
        { 
            Console.WriteLine("=========Using Fixed Data==========\r\n");
 
            //demo with fixed data
            ConditionalWeakTable<Person, ExtraPersonProps> cwtPerson =
                new ConditionalWeakTable<Person, ExtraPersonProps>();
            Person p = new Person();
            cwtPerson.Add(p, new ExtraPersonProps(1,"demoPerson"));
            ExtraPersonProps props;
            if (cwtPerson.TryGetValue(p, out props))
                Console.WriteLine(string.Format("value of Person is : Age {0}, Name: {1}",
                    props.Age, props.Name));
 
            Console.WriteLine("=========Using Dictionary==========\r\n");
 
            //demo with Dictonary data
            ConditionalWeakTable<Person, Dictionary<string, object>> cwtPerson2 =
                new ConditionalWeakTable<Person, Dictionary<string, object>>();
            Person p2 = new Person();
            Dictionary<string, object> data = new Dictionary<string, object>();
            data.Add("age", 2);
            data.Add("name", "demoPerson2");
            cwtPerson2.Add(p2, data);
            Dictionary<string, object> dataRetrieved;
            if (cwtPerson2.TryGetValue(p2, out dataRetrieved))
                Console.WriteLine(string.Format("value of Person is : Age {0}, Name: {1}",
                    dataRetrieved["age"], dataRetrieved["name"]));
  
            Console.ReadLine();
         }
    }
}
Which outputs this

=========Using Fixed Data==========

value of Person is : Age 1, Name: demoPerson

=========Using Dictionary==========

value of Person is : Age 2, Name: demoPerson2

有几点要注意下:

ConditionalWeakTable<TKey, TValue> 类使得语言编译器可在运行时给托管的对象附加任意属性。ConditionalWeakTable<TKey,
TValue> 对象是一个字典,它将一个键表示的托管对象绑定到一个值表示的附加属性。 该对象的键是 TKey 类的个体实例,属性附加到这个类上,且其值为分配到相应对象的属性值。

键必须唯一;换句话说,ConditionalWeakTable<TKey, TValue> 类支持每个托管对象一个附加值。 如果将两个键传递给 Object.ReferenceEquals 方法返回 true,这两个键相等。

尽管 ConditionalWeakTable<TKey, TValue> 类保存键/值对的集合,最好将其视为表而不是字典对象。ConditionalWeakTable<TKey,
TValue> 类在几个方面与字典不同:

它不保留键。 也就是说,键不会只是因为它是集合的成员而保持活动状态。

它并不能包括词典通常包含的所有方法(如 GetEnumerator 或 Contains)。

它未实现 IDictionary<TKey, TValue> 接口。

using System;
using System.Runtime.CompilerServices;

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.
using System;
using System.Runtime.CompilerServices;
using System.Threading;

public class ManagedObject
{
}

public class AttachedProperty
{
   public AttachedProperty(ManagedObject obj, int ctr)
   {
      this.obj = obj;
      this.ctr = ctr;
   }

   public int ctr;
   public ManagedObject obj; 
}

public class Example
{
   public static void Main()
   {
      // Create two managed objects.
      ManagedObject m1 = new ManagedObject();
      ManagedObject m2 = new ManagedObject();

      // Define their attached property values.
      AttachedProperty p1 = new AttachedProperty(null, 0);
      AttachedProperty p2 = new AttachedProperty(m1, 1);

      // Create the table and add the key/value pairs.
      var table = new ConditionalWeakTable<ManagedObject, AttachedProperty>();
      table.Add(m1, p1);
      table.Add(m2, p2);

      // Destroy m1.
      m1 = null;
      // Sleep for 1 second to allow m1 to be garbage collected.
      Thread.Sleep(1000);
      // Reinstantiate m1
      m1 = new ManagedObject();

      // Try to retrieve m1 and m2.
      AttachedProperty value = null;   
      if (table.TryGetValue(m2, out value))
         Console.WriteLine("m2: ({0}, {1})", value.obj, value.ctr);
      else
         Console.WriteLine("m2 is not in the table.");

      if (table.TryGetValue(m1, out value))
         Console.WriteLine("m1: ({0}, {1})", value.obj, value.ctr);
      else
         Console.WriteLine("m1 is not in the table.");
   }
}
// The example displays the following output:
//       m2: (ManagedObject, 1)
//       m1 is not in the table.
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: