Если вы можете использовать Реактивные расширения для .NET , вы можете упростить это.
Вы можете сделать Наблюдаемым из события и прослушивать только первый элемент, используя .Take(1)
, чтобы сделать свой небольшой фрагмент кода. Это превращает весь этот процесс в пару строк кода.
Редактировать: Для демонстрации я создал полный пример программы (я вставлю ниже).
Я переместил наблюдаемое создание и подписку в метод (HandleOneShot
). Это позволяет вам делать то, что вы пытаетесь, с помощью одного вызова метода. Для демонстрации я создал класс с двумя свойствами, который реализует INotifyPropertyChanged, и слушаю событие first измененное свойство, записывая в консоль, когда это происходит.
Это берет ваш код и изменяет его на:
HandleOneShot<SomeEventArgs>(variableOfSomeType, "SomeEvent", e => {
// Small snippet of code here
});
Обратите внимание, что вся подписка / отмена подписки происходит автоматически за кулисами. Нет необходимости вручную вводить подписку - просто подпишитесь на Observable, и Rx позаботится об этом за вас.
При запуске этот код печатает:
Setup...
Setting first property...
**** Prop2 Changed! /new val
Setting second property...
Setting first property again.
Press ENTER to continue...
Вы получаете только один, триггерный выстрел вашего события.
namespace ConsoleApplication1
{
using System;
using System.ComponentModel;
using System.Linq;
class Test : INotifyPropertyChanged
{
private string prop2;
private string prop;
public string Prop
{
get {
return prop;
}
set
{
if (prop != value)
{
prop = value;
if (PropertyChanged!=null)
PropertyChanged(this, new PropertyChangedEventArgs("Prop"));
}
}
}
public string Prop2
{
get
{
return prop2;
}
set
{
if (prop2 != value)
{
prop2 = value;
if (PropertyChanged != null)
PropertyChanged(this, new PropertyChangedEventArgs("Prop2"));
}
}
}
public event PropertyChangedEventHandler PropertyChanged;
}
class Program
{
static void HandleOneShot<TEventArgs>(object target, string eventName, Action<TEventArgs> action) where TEventArgs : EventArgs
{
var obsEvent = Observable.FromEvent<TEventArgs>(target, eventName).Take(1);
obsEvent.Subscribe(a => action(a.EventArgs));
}
static void Main(string[] args)
{
Test test = new Test();
Console.WriteLine("Setup...");
HandleOneShot<PropertyChangedEventArgs>(
test,
"PropertyChanged",
e =>
{
Console.WriteLine(" **** {0} Changed! {1}/{2}!", e.PropertyName, test.Prop, test.Prop2);
});
Console.WriteLine("Setting first property...");
test.Prop2 = "new value";
Console.WriteLine("Setting second property...");
test.Prop = "second value";
Console.WriteLine("Setting first property again...");
test.Prop2 = "other value";
Console.WriteLine("Press ENTER to continue...");
Console.ReadLine();
}
}
}