Skip to content

Instantly share code, notes, and snippets.

@julesx
Created May 28, 2022 19:21
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save julesx/2ca4a68cb5304dc9fc30cab1cc3d1033 to your computer and use it in GitHub Desktop.
Save julesx/2ca4a68cb5304dc9fc30cab1cc3d1033 to your computer and use it in GitHub Desktop.
public class CrazyTag : ICrazyTag
{
protected readonly List<Subscription> observables = new List<Subscription>();
protected readonly List<IObserver<ICrazyTag>> observers = new List<IObserver<ICrazyTag>>();
bool disposedValue = false;
protected CrazyTag() { }
IDisposable IObservable<ICrazyTag>.Subscribe(IObserver<ICrazyTag> observer)
{
if (!observers.Contains(observer))
{
observers.Add(observer);
observer.OnNext(this); //--> or not...maybe you'd set some InitialSubscription state
//--> to help the observer distinguish initial notification from changes
}
return new Subscription(this, observer, observers);
}
public bool SubscribeToTag(ICrazyTag tag)
{
if (observables.Any(subscription => subscription.Tag == tag)) return false; //--> could throw here
observables.Add((Subscription)tag.Subscribe(this));
return true;
}
public void ClearSubscriptions()
{
while (observables.Count > 0)
{
var sub = observables[0];
observables.RemoveAt(0);
((IDisposable)sub).Dispose();
}
}
public bool UnsubscribeFromTag(ICrazyTag tag)
{
observables.RemoveAll(subscription => subscription.Tag == tag);
return true;
}
protected void Notify() => observers.ForEach(observer => observer.OnNext(this));
public virtual void OnNext(ICrazyTag value) { }
public virtual void OnError(Exception error) { }
public virtual void OnCompleted() { }
public Type TagType => GetType();
protected virtual void Dispose(bool disposing)
{
if (!disposedValue)
{
if (disposing)
{
while (observables.Count > 0)
{
var sub = observables[0];
observables.RemoveAt(0);
((IDisposable)sub).Dispose();
}
}
disposedValue = true;
}
}
public void Dispose()
{
Dispose(true);
}
protected sealed class Subscription : IDisposable
{
readonly WeakReference<CrazyTag> tag;
readonly List<IObserver<ICrazyTag>> observers;
readonly IObserver<ICrazyTag> observer;
internal Subscription(CrazyTag tag, IObserver<ICrazyTag> observer, List<IObserver<ICrazyTag>> observers)
{
this.tag = new WeakReference<CrazyTag>(tag);
this.observers = observers;
this.observer = observer;
}
void IDisposable.Dispose()
{
if (observers.Contains(observer)) observers.Remove(observer);
}
public CrazyTag Tag
{
get
{
if (tag.TryGetTarget(out CrazyTag target))
{
return target;
}
return null;
}
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment