إنشاء طريقة تمديد غير قابلة للملاحظة لا تُرجع عنصرًا افتراضيًا لتسلسل فارغ

StackOverflow https://stackoverflow.com/questions/3864775

  •  28-09-2019
  •  | 
  •  

سؤال

تخيل بيان LINQ التالي إلى Observables:

var x = from result1 in service1.operation()
        from result2 in service2.operation()
        from result3 in service3.operation()
        select DoSomething()

x.Subscribe()

void Unit DoSomething() {
 ...
}

تعود جميع الخدمات إلى البرد القابل للملاحظة ، لذلك سوف ينتظرون إكمال كل واحد ثم يتم استدعاء شيء.

الآن هو Service2.Operation إرجاع الملاحظة. repty وهو في الأساس إشعار oncomplete وهذا يعني أن Service3 لن يتم استدعاؤه أبدًا ولا شيء.

أردت أن تستمر السلسلة إذا تم إرجاع onComplete ، ولكن توفير قيمة افتراضية للنتيجة 2. لذلك قمت بإنشاء طريقة تمديد onemptyreturndefault

public static IObservable<T> OnEmptyReturnDefault<T>(this IObservable<T> observable)
{
    var maybeReturnsSomething = observable.Memoize(); // Custom Lazy caching extension method
    var whenEmpty = from isEmpty in maybeReturnsSomething.IsEmpty()
                    where isEmpty
                    select default(T);
    var whenNotEmpty = from isEmpty in maybeReturnsSomething.IsEmpty()
                        where !isEmpty
                        from notEmpty in maybeReturnsSomething
                        select notEmpty;
    return whenEmpty.Merge(whenNotEmpty);
}

السماح لي أن أفعل:

var x = from result1 in service1.operation()
            from result2 in service2.operation().OnEmptyReturnDefault()
            from result3 in service3.operation()
            select DoSomething()

كل شيء جيد ، إلا أن حلي يحظر. isempty () لا يأخذ بشكل أساسي (1) .count () == 0. أريد حلًا لا يحظر.

هل كانت مفيدة؟

المحلول

حل مقترح في موقع آخر يعمل بشكل جيد:

public static IObservable<T> DefaultIfEmpty<T>(this IObservable<T> src, T defaultValue)
{
  return src
    .Materialize()
    .Select((n, i) => (n.Kind == NotificationKind.OnCompleted && i == 0)
                ? new Notification<T>[]
                {
                  new Notification<T>.OnNext(defaultValue), 
                  new Notification<T>.OnCompleted()
                }
                : new[] {n})
    .SelectMany(ns => ns)
    .Dematerialize();
}
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top