diff --git a/FacadeFor3e.Tests/AttributeCollectionTests.cs b/FacadeFor3e.Tests/AttributeCollectionTests.cs
index 0c11105..d17d6d5 100644
--- a/FacadeFor3e.Tests/AttributeCollectionTests.cs
+++ b/FacadeFor3e.Tests/AttributeCollectionTests.cs
@@ -164,6 +164,30 @@ public void SetAnItem()
ClassicAssert.AreEqual(n, coll[0]);
}
+ [Test]
+ public void TestSetOrReplace()
+ {
+ var coll = new AttributeCollection
+ {
+ new NamedAttributeValue("boolean", new BoolAttribute(true)),
+ new NamedAttributeValue("integer", new IntAttribute(25)),
+ new NamedAttributeValue("guid", new GuidAttribute(Guid.NewGuid()))
+ };
+
+ var g = new NamedAttributeValue("guid", new BoolAttribute(true));
+ var i = new NamedAttributeValue("integer", new IntAttribute(25));
+ var t = new NamedAttributeValue("date", new DateTimeAttribute(DateTime.Now));
+
+ coll.AddOrReplace(g);
+ coll.AddOrReplace(i);
+ coll.AddOrReplace(t);
+
+ ClassicAssert.AreEqual(4, coll.Count);
+ ClassicAssert.AreEqual(g, coll["guid"]);
+ ClassicAssert.AreEqual(i, coll["integer"]);
+ ClassicAssert.AreEqual(t, coll["date"]);
+ }
+
[Test]
public void GetErrors()
{
diff --git a/FacadeFor3e.Tests/FacadeFor3e.Tests.csproj b/FacadeFor3e.Tests/FacadeFor3e.Tests.csproj
index 6a9b454..27f1dca 100644
--- a/FacadeFor3e.Tests/FacadeFor3e.Tests.csproj
+++ b/FacadeFor3e.Tests/FacadeFor3e.Tests.csproj
@@ -7,7 +7,7 @@
-
+
diff --git a/FacadeFor3e/FacadeFor3e.csproj b/FacadeFor3e/FacadeFor3e.csproj
index 5f832f1..3737ee5 100644
--- a/FacadeFor3e/FacadeFor3e.csproj
+++ b/FacadeFor3e/FacadeFor3e.csproj
@@ -5,7 +5,7 @@
FacadeFor3E
J Saffron Consulting
FacadeFor3E
- 4.0.0-rc3
+ 4.0.0
A library that makes integrating with Elite 3E a little easier
Copyright © J Saffron Consulting Ltd 2014 - 2024
https://github.com/JonSaffron/FacadeFor3e
diff --git a/FacadeFor3e/ProcessCommandBuilder/AttributeCollection.cs b/FacadeFor3e/ProcessCommandBuilder/AttributeCollection.cs
index 14e1ee3..77c7e8c 100644
--- a/FacadeFor3e/ProcessCommandBuilder/AttributeCollection.cs
+++ b/FacadeFor3e/ProcessCommandBuilder/AttributeCollection.cs
@@ -24,7 +24,6 @@ public NamedAttributeValue this[string name]
{
if (name == null)
throw new ArgumentNullException(nameof(name));
- // ReSharper disable once PossibleNullReferenceException
var result = this.SingleOrDefault(a => a.Name.Equals(name, StringComparison.OrdinalIgnoreCase));
if (result == null)
throw new KeyNotFoundException("An attribute could not be found with the specified name.");
@@ -42,18 +41,39 @@ public bool TryGetValue(string name, [NotNullWhen(true)] out NamedAttributeValue
{
if (name == null)
throw new ArgumentNullException(nameof(name));
- // ReSharper disable once PossibleNullReferenceException
namedAttribute = this.SingleOrDefault(a => a.Name.Equals(name, StringComparison.OrdinalIgnoreCase));
return namedAttribute != null;
}
+ ///
+ /// Adds the specified attribute to the collection, or replaces it if an attribute with the same name is already present
+ ///
+ /// The attribute to add or to replace
+ /// If is null
+ public void AddOrReplace(NamedAttributeValue namedAttribute)
+ {
+ if (namedAttribute == null) throw new ArgumentNullException(nameof(namedAttribute));
+ for (int i = 0; i < this.Count; i++)
+ {
+ var a = this[i];
+
+ if (a.Name.Equals(namedAttribute.Name, StringComparison.OrdinalIgnoreCase))
+ {
+ // ReSharper disable once RedundantBaseQualifier
+ this.SetItem(i, namedAttribute);
+ return;
+ }
+ }
+
+ base.Add(namedAttribute);
+ }
+
///
// ReSharper disable once AnnotationConflictInHierarchy
protected override void InsertItem(int index, NamedAttributeValue item)
{
if (item == null)
throw new ArgumentNullException(nameof(item));
- // ReSharper disable once PossibleNullReferenceException
if (this.Any(a => a.Name.Equals(item.Name, StringComparison.OrdinalIgnoreCase)))
throw new ArgumentOutOfRangeException($"An attribute with the name {item.Name} has already been added.");
base.InsertItem(index, item);
@@ -71,8 +91,6 @@ protected override void SetItem(int index, NamedAttributeValue item)
continue;
var a = this[i];
- if (a == null)
- throw new InvalidOperationException();
if (a.Name.Equals(item.Name, StringComparison.OrdinalIgnoreCase))
throw new ArgumentOutOfRangeException($"An attribute with the name {item.Name} already exists.");
}
@@ -94,8 +112,6 @@ public bool Remove(string name)
{
var a = this[i];
- if (a == null)
- throw new InvalidOperationException();
if (a.Name.Equals(name, StringComparison.OrdinalIgnoreCase))
{
// ReSharper disable once RedundantBaseQualifier
diff --git a/FacadeFor3e/ReleaseHistory.md b/FacadeFor3e/ReleaseHistory.md
index d3a365e..8df27f7 100644
--- a/FacadeFor3e/ReleaseHistory.md
+++ b/FacadeFor3e/ReleaseHistory.md
@@ -1,4 +1,8 @@
-4.0.0-rc3
+4.0.0
+-----
+Added AddOrReplace to AttributeCollection to serve a particular use case
+
+4.0.0-rc3
---------
Change the ODataServiceResult.ErrorMesssages property to make it less brittle and enable it to cope with errors caused by rate limiting
Updated the json deserialiser to be case-insensitive and to cache the options object