2011-04-17 89 views
0


我目前正在C#中使用VariableWatcher类。
我想要做的是在每次将变量更改为特定值时引发一个事件。
例如:我有一个bool a,这是错误的。我将它传递给VariableWatcher类,并将其与应该引发事件的值true一起传递给VariableWatcher类。
我已经提出了解决这个问题的方法,但我显然误解了关于装箱/取消装箱的一些观点。
在C中存储对象的引用#

这是我的代码:

public class ValueWatch 
    { 
    public delegate void ValueTriggeredD(string ID, string valuename, object source); 
    public event ValueTriggeredD ValueTriggered; 

    Dictionary<string, object[]> LookUp = new Dictionary<string, object[]>(); //Key = ID, Value[0] = PropertyName, Value[1] = ObjTrigger, Value[2] = ObjWatch 
    Timer ttt; 

    public void Initialize() 
    { 
     ttt = new Timer(new TimerCallback(CB_T), null, 0, 50); 
    } 
    void CB_T(object o) 
    { 
     if (LookUp.Count > 0) 
     { 
      foreach (KeyValuePair<string, object[]> kvp in LookUp) 
      { 
       Type tp = kvp.Value[2].GetType(); 
       FieldInfo inf = tp.GetField((string)kvp.Value[0]); 
       if (inf != null) 
       { 
        object curval = inf.GetValue(kvp.Value[2]); 
        if (curval == kvp.Value[1]) 
        { 
         if (ValueTriggered != null) 
          ValueTriggered(kvp.Key, (string)kvp.Value[0], kvp.Value[2]); 
        } 
       } 
      } 
     } 
    } 
    public void StartWatching(string ID, object ListObj, object ValueForTrigger, string PropertyName) 
    { 
     if (LookUp.ContainsKey(ID)) 
      System.Diagnostics.Debug.Print("already there"); 
     else 
     { 
      LookUp.Add(ID, new object[] { PropertyName, ValueForTrigger, ListObj }); 
     } 
    } 
    public void StopWatching(string ID) 
    { 
     LookUp.Remove(ID); 
    } 
} 

我的问题是:为什么存储在该值的对象[2]而不是当我改变它的变化?

实施例:

bool b = false; 
valueWatch.ValueTriggered += new ValueTriggeredD(this.VT); 
valueWatch.StartWatching("ID1", this, true, "b"); 
... 
b = true; 
... 
void VT(string ID, string VN, object Source) 
{ 
    //Never triggered 
} 
+5

你也忘了问你的问题... – Oded 2011-04-17 13:39:10

+0

Ooops,对不起 - 编辑:) – alex 2011-04-17 13:48:08

+1

什么是重点这个?为什么不只是在setter调用某种ValueChanged()方法的时候创建一个属性? – Kon 2011-04-17 13:53:57

回答

1

这就是正确的。它永远不会触发。当你拳击有价值的类型时,你实际上会制作一份价值的副本并将其放入内存中。所以当你改变变量的值时,你并没有改变盒装值。其中浮现在脑海中的第一件事 - 使用不安全的上下文拳击变量地址但不幸的是.NET并不支持指针的拳击(from MSDN):

指针类型不从object继承和指针类型之间不存在转换目的。另外,装箱和拆箱不支持指针。但是,您可以在不同的指针类型之间以及指针类型和整型之间进行转换。

所以你唯一的可能的方式 - 使用不安全的环境和存储void*下面所有变量的地址:

 unsafe 
     { 
      bool test = false; 
      bool* adr = &test; 

      void* testObj = adr; 
      test = true; 
      Console.WriteLine("native test's value is" + test.ToString()); 
      Console.WriteLine("unboxed test's value is" + (*((bool*)testObj)).ToString()); 
     } 

但因为它在评论中提到的,为什么不实现事件将触发时财产已经改变?

1

我终于想出:

予设定值[2]对WeakReference到对象,而不是将其设置为对象的副本。
然后,我只需要得到WeakReference的价值,并有我的对象...

相关问题