PointSource.cs 2.1 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667
  1. using NModbus.Device;
  2. using NModbus.Unme.Common;
  3. using System;
  4. using System.Linq;
  5. namespace NModbus.Data
  6. {
  7. /// <summary>
  8. /// A simple implementation of the point source. Memory for all points is allocated the first time a point is accessed.
  9. /// This is useful for cases where many points are used.
  10. /// </summary>
  11. /// <typeparam name="T"></typeparam>
  12. public class PointSource<T> : IPointSource<T> where T : struct
  13. {
  14. public event EventHandler<PointEventArgs> BeforeRead;
  15. public event EventHandler<PointEventArgs<T>> BeforeWrite;
  16. public event EventHandler<PointEventArgs> AfterWrite;
  17. //Only create this if referenced.
  18. private readonly Lazy<T[]> _points;
  19. private readonly object _syncRoot = new object();
  20. private const int NumberOfPoints = ushort.MaxValue + 1;
  21. public PointSource()
  22. {
  23. _points = new Lazy<T[]>(() => new T[NumberOfPoints]);
  24. }
  25. public T[] ReadPoints(ushort startAddress, ushort numberOfPoints)
  26. {
  27. lock (_syncRoot)
  28. {
  29. return _points.Value
  30. .Slice(startAddress, numberOfPoints)
  31. .ToArray();
  32. }
  33. }
  34. T[] IPointSource<T>.ReadPoints(ushort startAddress, ushort numberOfPoints)
  35. {
  36. BeforeRead?.Invoke(this, new PointEventArgs(startAddress, numberOfPoints));
  37. return ReadPoints(startAddress, numberOfPoints);
  38. }
  39. public void WritePoints(ushort startAddress, T[] points)
  40. {
  41. lock (_syncRoot)
  42. {
  43. for (ushort index = 0; index < points.Length; index++)
  44. {
  45. _points.Value[startAddress + index] = points[index];
  46. }
  47. }
  48. }
  49. void IPointSource<T>.WritePoints(ushort startAddress, T[] points)
  50. {
  51. BeforeWrite?.Invoke(this, new PointEventArgs<T>(startAddress, points));
  52. WritePoints(startAddress, points);
  53. AfterWrite?.Invoke(this, new PointEventArgs(startAddress, (ushort)points.Length));
  54. }
  55. }
  56. }