Хранение ссылки на объект в C # - PullRequest
0 голосов
/ 17 апреля 2011


В настоящее время я работаю над классом VariableWatcher в C #.
Что я хочу сделать, это вызывать событие каждый раз, когда переменная изменяется на определенное значение.
Например,: У меня есть bool a, что неверноЯ передаю его классу VariableWatcher вместе со значением, на которое должно быть инициировано событие, true.
. Я уже подходил к решению этой проблемы, но, очевидно, неправильно понял некоторые моменты, касающиеся упаковки / распаковки.

Это мой код:

  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
}

Ответы [ 2 ]

1 голос
/ 17 апреля 2011

Я наконец понял:

Я установил для Value [2] значение WeakReference для объекта, а не для копии объекта.
Тогда мне нужно только получить значение из WeakReference, и там мой объект ...

1 голос
/ 17 апреля 2011

Это верно. Это никогда не сработает. Когда вы упаковываете ценные типы, вы фактически делаете копию значения и помещаете ее в память. Поэтому, когда вы меняете значение переменной, вы не меняете коробочное значение. Первое, что приходит на ум - использование небезопасного контекста для упаковки переменных адресов, но, к сожалению, .NET не поддерживает бокс указателей ( из MSDN ):

Типы указателей не наследуются от объекта, и между типами указателей и объектом не существует никаких преобразований. Кроме того, бокс и распаковка не поддерживают указатели. Однако вы можете конвертировать между различными типами указателей, а также между типами указателей и целочисленными типами.

Так что единственный возможный для вас способ - использовать небезопасный контекст и хранить адреса всех переменных в 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());
        }

Но, как упоминалось в комментариях, почему бы не реализовать событие, которое сработало бы при изменении свойства?

...