2015-01-04 2 views
-1

В теле моем классе, у меня есть эта строка кода:Как объединить эти две команды в одну?

private ReactiveCommand<object> _displayCommand = ReactiveCommand.Create(); 

В конструктор класса, настроить подписку:

_displayCommand.Subscribe(_ => 
{ 
    MessageBox.Show("Button clicked."); 
}); 

Можно ли написать какой-то расширение метод для эффективного объединения этих двух команд в один, поэтому с помощью одного вызова функции мы можем вызвать ReactiveCommand.Create() и создать подписку с помощью Reactive Extensions (RX)?

Это объединит все логически связанные коды и сделает ViewModel намного чище.

Update

Это то, что я до сих пор (спасибо @ jt000):

public static ReactiveCommand<object> CreateAndSubscribe(Func<object> fn) 
{ 
    var displayCommand = ReactiveCommand.Create(); 
    displayCommand.Subscribe<object>(_ => fn.Invoke()); 
    return displayCommand; 
} 

private ReactiveCommand<object> _displayCommand = CreateAndSubscribe(() => 
{ 
    return MessageBox.Show("Hello"); 
}); 

public ReactiveCommand<object> DisplayCommand 
{ 
    get { return _displayCommand; } 
    protected set { _displayCommand = value; } 
} 

Однако, мне нужно иногда вставить вызов .Buffer(TimeSpan.FromSeconds(1). между displayCommand и .Subscribe(fn), и эта функция недостаточно общего для этого. Мне действительно нужен способ передачи всей подписки на CreateAndSubscribe - возможно, Func, который принимает IObservable?

Это означает, что я мог бы использовать что-то вроде следующего вызова функции:

private ReactiveCommand<object> _displayCommand = 
    CreateAndSubscribe(o => o.Subscribe(() => 
           { 
            return MessageBox.Show("Hello"); 
           })); 

и если я хотел вставить .Buffer(TimeSpan.FromSeconds(1)):

private ReactiveCommand<object> _displayCommand = 
    CreateAndSubscribe(o => o.Buffer(TimeSpan.FromSeconds(1)).Subscribe(() => 
           { 
            return MessageBox.Show("Hello"); 
           })); 
+6

Все эти решения устраняют IDisposable, возвращенные из подписки, поэтому API не существует в первую очередь –

+0

@Paul Betts Во-первых, фантастическая работа над ReactiveUI, вы бог программирования среди нас простых смертных :) Если вы добавляете это как ответ, я буду отмечать его как официальный. – Contango

ответ

3

Этот API на самом деле намеренно отсутствует, потому что нет элегантный способ для Create вернуть какReactiveCommandиIDisposable результата от Create. Вы могли сделать что-то уродливое с параметрами out, но это закончилось бы довольно громоздким.

В то время как я определенно иногда пропускаю CreateWithAction или что-то в этом роде, немедленные Subscribe s - это своего рода победа в аспекте композиционной способности RxUI; этот API делает это сложнее, чтобы собрать вещи, а не проще.

+0

Как насчет обновления ReactiveCommand, чтобы он вызывал IDisposable на нем, он вызывает IDisposable для любых подписей, которыми он владеет? Это изящно и дает одно возвращаемое значение. Я мог бы увидеть, могу ли я написать это сам и посмотреть, как он летает. – Contango

2

бы эту работу?

public static ReactiveCommand<object> CreateAndSubscribe(Func<object> fn) 
{ 
    var displayCommand = ReactiveCommand.Create(); 
    displayCommand.Subscribe(fn); 
    return displayCommand; 
} 

Использование:

CreateAndSubscribe(_ => MessageBox.Show("hi")); 
+0

Спасибо! Тем не менее, я хотел бы получить общее решение, поэтому мне нужно каким-то образом передать подписку в качестве параметра. – Contango

+0

Будет ли это обновление работать? – jt000

+0

Спасибо. Я тоже это пробовал, но у меня все еще возникали проблемы. Если я хочу вставить вызов '.Buffer (TimeSpan.FromSeconds (1) .' между' displayCommand' и '.Subscribe (fn)', я не могу этого сделать. Мне действительно нужен способ передачи всего подписка в - возможно, какая-то функция, которая принимает IObservable? – Contango

1

Да, но там нет особого смысла, потому что члены экземпляра не в объеме при определении поля. Обработчики, которые вы передаете в Subscribe, не могут ссылаться ни на одно из полей модели представления, ни на вызов любого из его методов. Вы не сможете сделать гораздо больше, чем то, что вы показали в своем примере, например, позвонить MessageBox.Show или что-то в этом роде.

+0

Из моих экспериментов я считаю, что то, что мне нужно, будет в области видимости. Свойства, которые я ссылаюсь в подписке RX, являются фактически ленивыми свойствами, поэтому они инициализируются по требованию. – Contango

+0

Экземпляр члены (поля, свойства, методы и события) не входят в область определения поля экземпляра того же класса. Это так, как есть :) –

0

Поместите что-то подобное в статическом классе.

public static void CreateAndSubscribe(this displayCommand) 
    { 
     displayCommand = ReactiveCommand.Create(); 
     displayCommand.Subscribe(_ => 
     { 
      MessageBox.Show("Button clicked."); 
     }); 
    } 

доступа, как любой другой метод расширения:

_displayCommand.CreateAndSubscribe(); 
+0

Спасибо за этот ответ. Тем не менее, я хотел бы получить общее решение, поэтому мне нужно каким-то образом передать подписку в качестве параметра. У меня около 20 из этих вызовов, и было бы неплохо иметь одну общую строку, которая может инициализировать все (включая настройку подписки). – Contango

+0

Я не думаю, что это скомпилировалось (ReativeCommand - это класс, а не член displayCommand). – jt000

+0

да я могу удалить это и оставить команду отображения – prospector

Смежные вопросы