Skip to content

Commit

Permalink
Add Tests, Update Docs, Update code
Browse files Browse the repository at this point in the history
  • Loading branch information
ChrisPulman committed Jun 5, 2024
1 parent 70fb5a7 commit ab1b750
Show file tree
Hide file tree
Showing 15 changed files with 668 additions and 334 deletions.
2 changes: 1 addition & 1 deletion Directory.Build.props
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
<Nullable>enable</Nullable>
<PackageIcon>icon.png</PackageIcon>
<Configurations>Debug;Release;PreRelease</Configurations>
<PackageReleaseNotes>Compatability with Net 6 / 7 / 8 and netstandard2.0</PackageReleaseNotes>
<PackageReleaseNotes>Compatability with Net 6 / 8 and netstandard2.0</PackageReleaseNotes>
<PackageTags>Hashtable;rx;reactive;extensions;observable;LINQ;net;netstandard</PackageTags>
<EnableNETAnalyzers>True</EnableNETAnalyzers>
<AnalysisLevel>latest</AnalysisLevel>
Expand Down
41 changes: 40 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,2 +1,41 @@
# HashTableRx
A Reactive Hash Table
A Reactive Hash Table, used to store and observe values in a hash table reflecting the structure of an object.

## Usage

```csharp
// Replace YOUR_OBJECT with the object you want to store in the hash table
var obj = new YOUR_OBJECT();

// Create a new Hash Table - the bool is used to determine if the hash table should use Upper Case or Case Sensitive keys
var hashTable = new HashTableRx(false);

// Set / update the structure of the Hash Table
hashTable.SetStructure(obj);

hashTable.Observe<bool>("YourProperty").Subscribe(value =>
{
// Do something with the value
});

// Set the value in the hash table
hashTable.Value<float>("YourProperty", 10.5f);

// Get the value from the hash table
var value = hashTable.Value<float>("YourProperty");

// Get the current structure of the hash table
var updatedObj = hashTable.GetStructure();
```

## About

The HashTableRx can be used to store and observe values in a hash table reflecting the structure of an object. The HashTableRx is a reactive hash table, which means that you can observe the values in the hash table and react to changes in the values. The HashTableRx is a generic class, which means that you can store any type of object in the hash table. The HashTableRx is a lightweight and easy-to-use library that can be used in any C# project.

Variables in the HashTableRx are seperated by a dot, for example: "YourProperty.SubProperty".
This is used to reflect the layers of a structured object in the hash table.

Currently, the HashTableRx supports the following types:
Structures made of Public Fields both Primative and further layers of classes, itteration will be done to find the Primative values in a Structure.

ToDo: Add support for Properties.
2 changes: 1 addition & 1 deletion Version.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"$schema": "https://raw.githubusercontent.com/dotnet/Nerdbank.GitVersioning/main/src/NerdBank.GitVersioning/version.schema.json",
"version": "1.1",
"version": "1.2",
"publicReleaseRefSpec": [
"^refs/heads/master$",
"^refs/heads/main$"
Expand Down
39 changes: 39 additions & 0 deletions src/HashTableRx.Tests/HashTableRx.Tests.csproj
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>

<IsPackable>false</IsPackable>
<IsTestProject>true</IsTestProject>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="coverlet.collector" Version="6.0.2">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.10.0" />
<PackageReference Include="xunit" Version="2.8.1" />
<PackageReference Include="xunit.runner.visualstudio" Version="2.8.1">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
</ItemGroup>

<ItemGroup>
<ProjectReference Include="..\HashTableRx\HashTableRx.csproj" />
</ItemGroup>

<ItemGroup>
<Using Include="Xunit" />
</ItemGroup>

<ItemGroup>
<None Update="MockLibraryWithFields.dll">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
</ItemGroup>

</Project>
70 changes: 70 additions & 0 deletions src/HashTableRx.Tests/HashTableRxFixture.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
// Copyright (c) Chris Pulman. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.

using System.Reflection;

namespace CP.Collections.Tests
{
/// <summary>
/// HashTableRxFixture.
/// </summary>
/// <seealso cref="System.IDisposable" />
public class HashTableRxFixture : IDisposable
{
private bool _disposedValue;

/// <summary>
/// Initializes a new instance of the <see cref="HashTableRxFixture"/> class.
/// </summary>
public HashTableRxFixture()
{
// get the current directory
var currentDirectory = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);

// load the assembly MockLibraryWithFields.dll
var assembly = Assembly.LoadFrom(currentDirectory + "\\MockLibraryWithFields.dll");
Assert.NotNull(assembly);

// Create an instance of the MockLibraryWithFields.MockClassWithFields class
var obj = assembly.CreateInstance("TwinCATRx.RigSTRUCT");
Assert.NotNull(obj);

HtRx = new(false);
HtRx.SetStucture(obj);
}

/// <summary>
/// Gets the HashTable Rx.
/// </summary>
/// <value>
/// The ht rx.
/// </value>
public HashTableRx HtRx { get; }

/// <summary>
/// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources.
/// </summary>
public void Dispose()
{
Dispose(disposing: true);
GC.SuppressFinalize(this);
}

/// <summary>
/// Releases unmanaged and - optionally - managed resources.
/// </summary>
/// <param name="disposing"><c>true</c> to release both managed and unmanaged resources; <c>false</c> to release only unmanaged resources.</param>
protected virtual void Dispose(bool disposing)
{
if (!_disposedValue)
{
if (disposing)
{
HtRx.Dispose();
}

_disposedValue = true;
}
}
}
}
100 changes: 100 additions & 0 deletions src/HashTableRx.Tests/HashTableRxTest.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
// Copyright (c) Chris Pulman. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.

using System.Reactive.Disposables;
using System.Reactive.Linq;

namespace CP.Collections.Tests
{
/// <summary>
/// UnitTest1.
/// </summary>
/// <remarks>
/// Initializes a new instance of the <see cref="HashTableRxTest"/> class.
/// </remarks>
/// <param name="fixture">The hash table rx fixture.</param>
public class HashTableRxTest(HashTableRxFixture fixture) : IClassFixture<HashTableRxFixture>
{
/// <summary>
/// Test1s this instance.
/// </summary>
[Fact]
public void HashTableRxCanReadValuesDirectly()
{
fixture.HtRx["CalibrationDataValid"] = false;
var t = (bool?)fixture.HtRx["CalibrationDataValid"];
Assert.False(t);

fixture.HtRx["Casing.Temperature.PV.Value"] = 0.0f;
var t2 = (float?)fixture.HtRx["Casing.Temperature.PV.Value"];
Assert.Equal(0.0f, t2);
}

/// <summary>
/// Hashes the table rx can write values.
/// </summary>
[Fact]
public void HashTableRxCanWriteValuesDirectly()
{
fixture.HtRx["CalibrationDataValid"] = true;
var t = (bool?)fixture.HtRx["CalibrationDataValid"];
Assert.True(t);

fixture.HtRx["Casing.Temperature.PV.Value"] = 1.0f;
var t2 = (float?)fixture.HtRx["Casing.Temperature.PV.Value"];
Assert.Equal(1.0f, t2);
}

/// <summary>
/// Hashes the table rx can read values from observable.
/// </summary>
[Fact]
public void HashTableRxCanReadValuesFromObservable()
{
var disposables = new CompositeDisposable();
fixture.HtRx["CalibrationDataValid"] = false;
var t = (bool?)fixture.HtRx["CalibrationDataValid"];
Assert.False(t);
disposables.Add(fixture.HtRx.Observe<bool>("CalibrationDataValid").Skip(1).Subscribe(x => Assert.True(x)));
fixture.HtRx["CalibrationDataValid"] = true;

fixture.HtRx["Casing.Temperature.PV.Value"] = 0.0f;
var t2 = (float?)fixture.HtRx["Casing.Temperature.PV.Value"];
Assert.Equal(0.0f, t2);
disposables.Add(fixture.HtRx.Observe<float>("Casing.Temperature.PV.Value").Skip(1).Subscribe(x => Assert.Equal(1.0f, x)));
fixture.HtRx["Casing.Temperature.PV.Value"] = 1.0f;

disposables.Dispose();
}

/// <summary>
/// Hashes the table rx can read values.
/// </summary>
[Fact]
public void HashTableRxCanReadValues()
{
fixture.HtRx["CalibrationDataValid"] = false;
var t = fixture.HtRx.Value<bool>("CalibrationDataValid");
Assert.False(t);

fixture.HtRx["Casing.Temperature.PV.Value"] = 0.0f;
var t2 = fixture.HtRx.Value<float>("Casing.Temperature.PV.Value");
Assert.Equal(0.0f, t2);
}

/// <summary>
/// Hashes the table rx can write values.
/// </summary>
[Fact]
public void HashTableRxCanWriteValues()
{
fixture.HtRx.Value("CalibrationDataValid", true);
var t = fixture.HtRx.Value<bool>("CalibrationDataValid");
Assert.True(t);

fixture.HtRx.Value("Casing.Temperature.PV.Value", 1.0f);
var t2 = fixture.HtRx.Value<float>("Casing.Temperature.PV.Value");
Assert.Equal(1.0f, t2);
}
}
}
Binary file not shown.
9 changes: 8 additions & 1 deletion src/HashTableRx.sln
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 17
VisualStudioVersion = 17.3.32922.545
Expand All @@ -18,6 +17,8 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "SolutionConfig", "SolutionC
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "_build", "..\build\_build.csproj", "{5A3634B0-A15E-4B5D-8367-7D9FD0EACEE2}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "HashTableRx.Tests", "HashTableRx.Tests\HashTableRx.Tests.csproj", "{1DF2E1C4-3A84-4A32-A11C-0FD053D22696}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Expand All @@ -31,6 +32,12 @@ Global
{0B3BCECD-D330-4704-82B1-83EEB8C9A808}.PreRelease|Any CPU.Build.0 = PreRelease|Any CPU
{0B3BCECD-D330-4704-82B1-83EEB8C9A808}.Release|Any CPU.ActiveCfg = Release|Any CPU
{0B3BCECD-D330-4704-82B1-83EEB8C9A808}.Release|Any CPU.Build.0 = Release|Any CPU
{1DF2E1C4-3A84-4A32-A11C-0FD053D22696}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{1DF2E1C4-3A84-4A32-A11C-0FD053D22696}.Debug|Any CPU.Build.0 = Debug|Any CPU
{1DF2E1C4-3A84-4A32-A11C-0FD053D22696}.PreRelease|Any CPU.ActiveCfg = PreRelease|Any CPU
{1DF2E1C4-3A84-4A32-A11C-0FD053D22696}.PreRelease|Any CPU.Build.0 = PreRelease|Any CPU
{1DF2E1C4-3A84-4A32-A11C-0FD053D22696}.Release|Any CPU.ActiveCfg = Release|Any CPU
{1DF2E1C4-3A84-4A32-A11C-0FD053D22696}.Release|Any CPU.Build.0 = Release|Any CPU
{5A3634B0-A15E-4B5D-8367-7D9FD0EACEE2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{5A3634B0-A15E-4B5D-8367-7D9FD0EACEE2}.PreRelease|Any CPU.ActiveCfg = Release|Any CPU
{5A3634B0-A15E-4B5D-8367-7D9FD0EACEE2}.PreRelease|Any CPU.Build.0 = Release|Any CPU
Expand Down
Loading

0 comments on commit ab1b750

Please sign in to comment.