반응성 연장선을 사용한 첫 번째 흔들림 단계
-
20-09-2019 - |
문제
나는 나의 첫 번째 간단한 "Hello World"RX 응용 프로그램으로 어려움을 겪고 있습니다. VS2010 RC와 최신 RX 다운로드를 사용하고 있습니다.
다음은 간단한 콘솔 앱입니다.
class Program
{
static void Main(string[] args)
{
var channel = new MessageChannel()
.Where(m => m.process)
.Subscribe((MyMessage m) => Console.WriteLine(m.subject));
//channel.GenerateMsgs();
}
}
public class MyMessage
{
public string subject;
public bool process;
}
public class MessageChannel: IObservable<MyMessage>
{
List<IObserver<MyMessage>> observers = new List<IObserver<MyMessage>>();
public IDisposable Subscribe(IObserver<MyMessage> observer)
{
observers.Add(observer);
return observer as IDisposable;
}
public void GenerateMsgs()
{
foreach (IObserver<MyMessage> observer in observers)
{
observer.OnNext(new MyMessage() {subject = "Hello!", process = true});
}
}
}
Where 절에서 인수를 얻습니다. 여기에 스택이 있습니다.
System.ArgumentNullException was unhandled
Message=Value cannot be null.
Parameter name: disposable
Source=System.Reactive
ParamName=disposable
StackTrace:
at System.Collections.Generic.AnonymousObservable`1.Disposable.Set(IDisposable disposable)
at System.Collections.Generic.AnonymousObservable`1.<>c__DisplayClass1.<Subscribe>b__0()
at System.Threading.Scheduler.NowScheduler.Schedule(Action action)
at System.Collections.Generic.AnonymousObservable`1.Subscribe(IObserver`1 observer)
at ConsoleApplication1.Program.Main(String[] args) in C:\Users\Jason\documents\visual studio 2010\Projects\ConsoleApplication1\ConsoleApplication1\Program.cs:line 18
at System.AppDomain._nExecuteAssembly(RuntimeAssembly assembly, String[] args)
at System.AppDomain.ExecuteAssembly(String assemblyFile, Evidence assemblySecurity, String[] args)
at Microsoft.VisualStudio.HostingProcess.HostProc.RunUsersAssembly()
at System.Threading.ThreadHelper.ThreadStart_Context(Object state)
at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean ignoreSyncCtx)
at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)
at System.Threading.ThreadHelper.ThreadStart()
InnerException:
해결책
이 라인은 소란을 일으키는 것 같습니다.
return observer as IDisposable;
관찰자가 일회용이라고 가정해서는 안되며, "구독 취소"에 대해 알고있는 일회용 물체를 반환해야합니다.
이 메소드는 idisposable 인터페이스에 대한 참조를 반환합니다. 이를 통해 관찰자는 공급자가 보내기 전에 구독 취소 (즉, 알림 수신을 중단) 할 수 있습니다.
다음과 같은 작업을 수행하여 작동하게 할 수 있습니다.
public class MessageChannel: IObservable<MyMessage>
{
class Subscription : IDisposable {
MessageChannel _c;
IObservable<MyMessage> _obs;
public Subscription(MessageChannel c, IObservable<MyMessage> obs) {
_c = c; _obs = obs;
}
public void Dispose() {
_c.Unsubscribe(_obs);
}
}
public IDisposable Subscribe(IObserver<MyMessage> observer)
{
observers.Add(observer);
return new Subscription(this, observer);
}
void Unsubscribe(IObservable<MyMessage> obs) {
observers.Remove(obs);
}
}
다른 팁
!!빨간 깃발!!
나는 당신이 구현하지 않는다고 강력하게 제안합니다 IObserver<T>
또는 IObservable<T>
당신 자신. 사용을 선호합니다 Observable.Create<T>
또는 최후의 수단으로 사용하십시오 Subject
유형. 올바른 RX 유형 및 연산자가 처리하는 이러한 인터페이스를 올바르게 구현하기 위해 고려해야 할 사항이 많이 있습니다.
이 예에서는 MessageChannel 유형을 떨어 뜨리고 교체 할 것을 촉구합니다.
class Program
{
static void Main(string[] args)
{
var channel = GenerateMsgs()
.Where(m => m.process)
.Subscribe((MyMessage m) => Console.WriteLine(m.subject));
}
public IObservable<MyMessage> GenerateMsgs()
{
return Observable.Create<MyMessage>(observer=>
{
observer.OnNext(new MyMessage() {subject = "Hello!", process = true});
});
}
}
public class MyMessage
{
public string subject;
public bool process;
}
시스템 설계를 추가로 검사 할 때 "채널"을 관찰 가능한 시퀀스로 노출시키는 일종의 서비스가있을 수 있습니다.
public interface OrderService
{
IObservable<OrderRequest> OrderRequests();
IObservable<Order> ProcessedOrders();
IObservable<OrderRejection> OrdersRejections();
}
따라서 이러한 사용자 정의 구현의 필요성을 부정합니다 IObserver<T>
또는 IObservable<T>
.
제휴하지 않습니다 StackOverflow