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

View File

@ -2,6 +2,10 @@
namespace DTLib namespace DTLib
{ {
public delegate Task EventHandlerAsync<TEventArgs>(TEventArgs e); // по идее это нужно, чтоб делать так: SomeEvent?.Invoke().Wait()
public delegate Task EventHandlerAsync(); 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); b.Append(input);
return b.ToString(); 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; public static void Throw(this Exception ex) => throw ex;
@ -221,5 +228,13 @@ namespace DTLib
{ {
if (input is null) if_true(); 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() { }
public ReactiveListener(ReactiveStream<T> stream) : base(stream) { } 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) public event Action<ReactiveStream<T>, T> ElementAddedEvent;
{ void ElementAdded(ReactiveStream<T> stream, TimeSignedObject<T> e) => ElementAdded(stream, e.Value);
lock (Stream) ElementAddedHandler = handler; void ElementAdded(ReactiveStream<T> stream, T e) =>
} Task.Run(() => ElementAddedEvent?.Invoke(stream, e));
public async Task ElementAdded(T e) => await Task.Run(() => ElementAddedHandler?.Invoke(e));
public override void Join(ReactiveStream<T> stream) public override void Join(ReactiveStream<T> stream)
{ {
base.Join(stream); base.Join(stream);
lock (Stream) stream.ElementAddedEvent += ElementAdded; lock (Streams) stream.ElementAddedEvent += ElementAdded;
} }
public override void Leave(ReactiveStream<T> stream) public override void Leave(ReactiveStream<T> stream)
{ {
base.Leave(stream); base.Leave(stream);
lock (Stream) stream.ElementAddedEvent -= ElementAdded; lock (Streams) stream.ElementAddedEvent -= ElementAdded;
} }
public T GetFirstElement() => Stream[0]; public T GetFirst()
public T GetLastElement() => Stream[Stream.Length - 1]; {
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) => public T FindOne(Func<T, bool> condition)
/*foreach (T el in Stream) {
if (condition(el)) if (Streams.Count == 0) throw new Exception("ReactiveListener is not connected to any streams");
return el;*/ foreach (ReactiveStream<T> stream in Streams)
default; 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) public List<T> FindAll(Func<T, bool> condition)
{ {
List<T> elements = new(); if (Streams.Count == 0) throw new Exception("ReactiveListener is not connected to any streams");
/*foreach (T el in Stream) List<T> rezults = new();
if (condition(el)) foreach (ReactiveStream<T> stream in Streams)
elements.Add(el);*/ foreach (TimeSignedObject<T> el in stream)
return elements; 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> public abstract class ReactiveProvider<T>
{ {
protected ReactiveStream<T> Stream protected List<ReactiveStream<T>> Streams
{ {
get get
{ lock (_stream) return _stream; } { lock (_streams) return _streams; }
set set
{ lock (_stream) _stream = value; } { lock (_streams) _streams = value; }
} }
protected ReactiveStream<T> _stream; private List<ReactiveStream<T>> _streams = new();
public ReactiveProvider() { } public ReactiveProvider() { }
public ReactiveProvider(ReactiveStream<T> stream) => Streams.Add(stream);
public ReactiveProvider(ReactiveStream<T> stream) => Join(stream); public ReactiveProvider(ICollection<ReactiveStream<T>> streams) => Streams = streams.ToList();
public virtual void Join(ReactiveStream<T> stream) 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) 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 class ReactiveSender<T> : ReactiveProvider<T>
{ {
public ReactiveSender() { } public ReactiveSender() { }
public ReactiveSender(ReactiveStream<T> stream) : base(stream) { } public ReactiveSender(ReactiveStream<T> stream) : base(stream) { }
public ReactiveSender(ICollection<ReactiveStream<T>> streams) : base(streams) { }
public void Send(T e) 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 namespace DTLib.Reactive
{ {
public class ReactiveStream<T> public class ReactiveStream<T> : IEnumerable<TimeSignedObject<T>>, IList<TimeSignedObject<T>>
{ {
public ReactiveStream() { } public ReactiveStream() { }
List<T> _storage = new(); List<TimeSignedObject<T>> _storage = new();
List<T> Storage List<TimeSignedObject<T>> Storage
{ {
get get
{ lock (Storage) return _storage; } { lock (_storage) return _storage; }
} }
public int Length public int Count => Storage.Count;
public TimeSignedObject<T> this[int index]
{ {
get get => Storage[index];
{ lock (Storage) return Storage.Count; } set => throw new NotImplementedException();
} }
public T this[int index] public event Action<ReactiveStream<T>, TimeSignedObject<T>> ElementAddedEvent;
public void Add(TimeSignedObject<T> elem)
{ {
get Storage.Add(elem);
{ lock (Storage) return Storage[index]; } 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); public Enumerator(List<TimeSignedObject<T>> storage)
ElementAddedEvent?.Invoke(elem); {
_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;
}
}
}