reactivity

This commit is contained in:
Timerix22 2021-11-02 01:01:20 +03:00
parent 8e8c63e3f2
commit ea54bed80d
8 changed files with 183 additions and 50 deletions

View File

@ -55,6 +55,7 @@
<Compile Include="Reactive\ReactiveSender.cs" />
<Compile Include="Reactive\ReactiveStream.cs" />
<Compile Include="Reactive\ReactiveProvider.cs" />
<Compile Include="Reactive\TimeSignedObject.cs" />
<Compile Include="SecureRandom.cs" />
<Compile Include="FrameworkFix.cs" />
<Compile Include="TImer.cs" />
@ -62,7 +63,6 @@
</ItemGroup>
<ItemGroup>
<Content Include=".gitignore" />
<Content Include="DTLib.sln" />
</ItemGroup>
<ItemGroup>
<None Include="README.md" />

View File

@ -2,6 +2,10 @@
namespace DTLib
{
public delegate Task EventHandlerAsync<TEventArgs>(TEventArgs e);
public delegate Task EventHandlerAsync();
// по идее это нужно, чтоб делать так: SomeEvent?.Invoke().Wait()
public delegate Task EventHandlerAsyncDelegate();
public delegate Task EventHandlerAsyncDelegate<T>(T e);
public delegate Task EventHandlerAsyncDelegate<T0, T1>(T0 e0, T1 e1);
public delegate Task EventHandlerAsyncDelegate<T0, T1, T2>(T0 e0, T1 e1, T2 e2);
public delegate Task EventHandlerAsyncDelegate<T0, T1, T2, T3>(T0 e0, T1 e1, T2 e2, T3 e3);
}

View File

@ -152,6 +152,13 @@ namespace DTLib
b.Append(input);
return b.ToString();
}
public static string Multiply(this char input, int howMany)
{
StringBuilder b = new();
for (int i = 0; i < howMany; i++)
b.Append(input);
return b.ToString();
}
public static void Throw(this Exception ex) => throw ex;
@ -221,5 +228,13 @@ namespace DTLib
{
if (input is null) if_true();
}
public static string AddZeroes<T>(this T number, int length)
{
var str = number.ToString();
//var diff = str.Length -length ;
//if (diff > 0)
return Multiply('0', str.Length - length) + str;
}
}
}

View File

@ -8,42 +8,93 @@ namespace DTLib.Reactive
{
public ReactiveListener() { }
public ReactiveListener(ReactiveStream<T> stream) : base(stream) { }
public ReactiveListener(ICollection<ReactiveStream<T>> streams) : base(streams) { }
public EventHandlerAsync<T> ElementAddedHandler;
public void SetHandler(EventHandlerAsync<T> handler)
{
lock (Stream) ElementAddedHandler = handler;
}
public async Task ElementAdded(T e) => await Task.Run(() => ElementAddedHandler?.Invoke(e));
public event Action<ReactiveStream<T>, T> ElementAddedEvent;
void ElementAdded(ReactiveStream<T> stream, TimeSignedObject<T> e) => ElementAdded(stream, e.Value);
void ElementAdded(ReactiveStream<T> stream, T e) =>
Task.Run(() => ElementAddedEvent?.Invoke(stream, e));
public override void Join(ReactiveStream<T> stream)
{
base.Join(stream);
lock (Stream) stream.ElementAddedEvent += ElementAdded;
lock (Streams) stream.ElementAddedEvent += ElementAdded;
}
public override void Leave(ReactiveStream<T> stream)
{
base.Leave(stream);
lock (Stream) stream.ElementAddedEvent -= ElementAdded;
lock (Streams) stream.ElementAddedEvent -= ElementAdded;
}
public T GetFirstElement() => Stream[0];
public T GetLastElement() => Stream[Stream.Length - 1];
public T GetFirst()
{
if (Streams.Count == 0) throw new Exception("ReactiveListener is not connected to any streams");
TimeSignedObject<T> rezult = null;
foreach (ReactiveStream<T> stream in Streams)
if (stream.Count != 0)
{
TimeSignedObject<T> e = stream[0];
if (rezult is null) rezult = e;
else if (rezult.Time > e.Time) rezult = e;
}
return rezult.Value;
}
public T GetLast()
{
if (Streams.Count == 0) throw new Exception("ReactiveListener is not connected to any streams");
TimeSignedObject<T> rezult = null;
foreach (ReactiveStream<T> stream in Streams)
if (stream.Count != 0)
{
TimeSignedObject<T> e = stream[stream.Count - 1];
if (rezult is null) rezult = e;
else if (rezult.Time < e.Time) rezult = e;
}
return rezult.Value;
}
public T FindOne(Func<T, bool> condition) =>
/*foreach (T el in Stream)
if (condition(el))
return el;*/
default;
public T FindOne(Func<T, bool> condition)
{
if (Streams.Count == 0) throw new Exception("ReactiveListener is not connected to any streams");
foreach (ReactiveStream<T> stream in Streams)
foreach (TimeSignedObject<T> el in stream)
if (condition(el.Value))
return el.Value;
return default;
}
public TimeSignedObject<T> FindOne(Func<TimeSignedObject<T>, bool> condition)
{
if (Streams.Count == 0) throw new Exception("ReactiveListener is not connected to any streams");
foreach (ReactiveStream<T> stream in Streams)
foreach (TimeSignedObject<T> el in stream)
if (condition(el))
return el;
return default;
}
public List<T> FindAll(Func<T, bool> condition)
{
List<T> elements = new();
/*foreach (T el in Stream)
if (condition(el))
elements.Add(el);*/
return elements;
if (Streams.Count == 0) throw new Exception("ReactiveListener is not connected to any streams");
List<T> rezults = new();
foreach (ReactiveStream<T> stream in Streams)
foreach (TimeSignedObject<T> el in stream)
if (condition(el.Value))
rezults.Add(el.Value);
return rezults;
}
public List<TimeSignedObject<T>> FindAll(Func<TimeSignedObject<T>, bool> condition)
{
if (Streams.Count == 0) throw new Exception("ReactiveListener is not connected to any streams");
List<TimeSignedObject<T>> rezults = new();
foreach (ReactiveStream<T> stream in Streams)
foreach (TimeSignedObject<T> el in stream)
if (condition(el))
rezults.Add(el);
return rezults;
}
}
}

View File

@ -1,28 +1,35 @@
namespace DTLib.Reactive
using System;
using System.Collections.Generic;
using System.Linq;
namespace DTLib.Reactive
{
public abstract class ReactiveProvider<T>
{
protected ReactiveStream<T> Stream
protected List<ReactiveStream<T>> Streams
{
get
{ lock (_stream) return _stream; }
{ lock (_streams) return _streams; }
set
{ lock (_stream) _stream = value; }
{ lock (_streams) _streams = value; }
}
protected ReactiveStream<T> _stream;
private List<ReactiveStream<T>> _streams = new();
public ReactiveProvider() { }
public ReactiveProvider(ReactiveStream<T> stream) => Join(stream);
public ReactiveProvider(ReactiveStream<T> stream) => Streams.Add(stream);
public ReactiveProvider(ICollection<ReactiveStream<T>> streams) => Streams = streams.ToList();
public virtual void Join(ReactiveStream<T> stream)
{
lock (Stream) Stream = stream;
if (IsConnetcedTo(stream)) throw new Exception("ReactiveListener is already connected to the stream");
Streams.Add(stream);
}
public virtual void Leave(ReactiveStream<T> stream)
{
lock (Stream) Stream = null;
if (!Streams.Remove(stream)) throw new Exception("ReactiveListener is not connected to the stream");
}
public bool IsConnetcedTo(ReactiveStream<T> stream) => Streams.Contains(stream);
}
}

View File

@ -1,14 +1,18 @@
namespace DTLib.Reactive
using System.Collections.Generic;
namespace DTLib.Reactive
{
public class ReactiveSender<T> : ReactiveProvider<T>
{
public ReactiveSender() { }
public ReactiveSender(ReactiveStream<T> stream) : base(stream) { }
public ReactiveSender(ICollection<ReactiveStream<T>> streams) : base(streams) { }
public void Send(T e)
{
lock (Stream) Stream.Add(e);
foreach (ReactiveStream<T> s in Streams)
s.Add(e);
}
}
}

View File

@ -1,38 +1,74 @@
using System.Collections.Generic;
using System;
using System.Collections;
using System.Collections.Generic;
namespace DTLib.Reactive
{
public class ReactiveStream<T>
public class ReactiveStream<T> : IEnumerable<TimeSignedObject<T>>, IList<TimeSignedObject<T>>
{
public ReactiveStream() { }
List<T> _storage = new();
List<T> Storage
List<TimeSignedObject<T>> _storage = new();
List<TimeSignedObject<T>> Storage
{
get
{ lock (Storage) return _storage; }
{ lock (_storage) return _storage; }
}
public int Length
public int Count => Storage.Count;
public TimeSignedObject<T> this[int index]
{
get
{ lock (Storage) return Storage.Count; }
get => Storage[index];
set => throw new NotImplementedException();
}
public T this[int index]
public event Action<ReactiveStream<T>, TimeSignedObject<T>> ElementAddedEvent;
public void Add(TimeSignedObject<T> elem)
{
get
{ lock (Storage) return Storage[index]; }
Storage.Add(elem);
ElementAddedEvent?.Invoke(this, elem);
}
public void Add(T elem) => Add(new TimeSignedObject<T>(elem));
internal event EventHandlerAsync<T> ElementAddedEvent;
public void Clear() => Storage.Clear();
public int IndexOf(TimeSignedObject<T> item) => Storage.IndexOf(item);
public bool Contains(TimeSignedObject<T> item) => Storage.Contains(item);
internal void Add(T elem)
public IEnumerator<TimeSignedObject<T>> GetEnumerator() => new Enumerator(Storage);
IEnumerator IEnumerable.GetEnumerator() => new Enumerator(Storage);
struct Enumerator : IEnumerator<TimeSignedObject<T>>
{
lock (Storage) Storage.Add(elem);
ElementAddedEvent?.Invoke(elem);
public Enumerator(List<TimeSignedObject<T>> storage)
{
_storage = storage;
_index = storage.Count - 1;
}
List<TimeSignedObject<T>> _storage;
int _index;
public TimeSignedObject<T> Current => _storage[_index];
object IEnumerator.Current => Current;
public void Dispose() => _storage = null;
public bool MoveNext()
{
if (_index < 0)
return false;
_index--;
return true;
}
public void Reset() => _index = _storage.Count - 1;
}
internal void Clear() { lock (Storage) Storage.Clear(); }
bool ICollection<TimeSignedObject<T>>.IsReadOnly { get; } = false;
public void Insert(int index, TimeSignedObject<T> item) => throw new NotImplementedException();
public void RemoveAt(int index) => throw new NotImplementedException();
public void CopyTo(TimeSignedObject<T>[] array, int arrayIndex) => throw new NotImplementedException();
public bool Remove(TimeSignedObject<T> item) => throw new NotImplementedException();
}
}

View File

@ -0,0 +1,16 @@
using System;
namespace DTLib.Reactive
{
public class TimeSignedObject<T>
{
public T Value { get; init; }
public long Time { get; init; }
public TimeSignedObject(T value)
{
Value = value;
Time = DateTime.Now.Ticks;
}
}
}