diff --git a/SabreTools.Metadata.Filter.Test/FilterObjectTests.cs b/SabreTools.Metadata.Filter.Test/FilterObjectTests.cs
index 740cd32a..0891efee 100644
--- a/SabreTools.Metadata.Filter.Test/FilterObjectTests.cs
+++ b/SabreTools.Metadata.Filter.Test/FilterObjectTests.cs
@@ -1898,5 +1898,89 @@ namespace SabreTools.Metadata.Filter.Test
}
#endregion
+
+ #region SharedFeat
+
+ [Theory]
+ [InlineData("sharedfeat.name", "name")]
+ [InlineData("sharedfeat.value", "value")]
+ public void Matches_SharedFeat(string itemField, string value)
+ {
+ var filter = new FilterObject(itemField, value, Operation.Equals);
+ SharedFeat obj = new SharedFeat
+ {
+ Name = "name",
+ Value = "value",
+ };
+
+ bool actual = filter.Matches(obj);
+ Assert.True(actual);
+ }
+
+ #endregion
+
+ #region Slot
+
+ [Theory]
+ [InlineData("slot.name", "name")]
+ public void Matches_Slot(string itemField, string value)
+ {
+ var filter = new FilterObject(itemField, value, Operation.Equals);
+ Slot obj = new Slot
+ {
+ Name = "name",
+ };
+
+ bool actual = filter.Matches(obj);
+ Assert.True(actual);
+ }
+
+ #endregion
+
+ #region SlotOption
+
+ [Theory]
+ [InlineData("slotoption.default", "yes")]
+ [InlineData("slotoption.devname", "devname")]
+ [InlineData("slotoption.name", "name")]
+ public void Matches_SlotOption(string itemField, string value)
+ {
+ var filter = new FilterObject(itemField, value, Operation.Equals);
+ SlotOption obj = new SlotOption
+ {
+ Default = true,
+ DevName = "devname",
+ Name = "name",
+ };
+
+ bool actual = filter.Matches(obj);
+ Assert.True(actual);
+ }
+
+ #endregion
+
+ #region SoftwareList
+
+ [Theory]
+ [InlineData("softwarelist.filter", "filter")]
+ [InlineData("softwarelist.name", "name")]
+ [InlineData("softwarelist.status", "original")]
+ [InlineData("softwarelist.tag", "tag")]
+ public void Matches_SoftwareList(string itemField, string value)
+ {
+ var filter = new FilterObject(itemField, value, Operation.Equals);
+ SoftwareList obj = new SoftwareList
+ {
+ Filter = "filter",
+ Name = "name",
+ Status = SoftwareListStatus.Original,
+ Tag = "tag",
+ };
+
+ bool actual = filter.Matches(obj);
+ Assert.True(actual);
+ }
+
+ #endregion
}
}
diff --git a/SabreTools.Metadata.Filter/FilterKey.cs b/SabreTools.Metadata.Filter/FilterKey.cs
index 42bd62a8..5e54de55 100644
--- a/SabreTools.Metadata.Filter/FilterKey.cs
+++ b/SabreTools.Metadata.Filter/FilterKey.cs
@@ -1,6 +1,4 @@
using System;
-using System.Reflection;
-using System.Xml.Serialization;
using SabreTools.Data.Models.Metadata;
namespace SabreTools.Metadata.Filter
@@ -735,6 +733,44 @@ namespace SabreTools.Metadata.Filter
"savechipserial",
];
+ ///
+ /// Known keys for SharedFeat
+ ///
+ private static readonly string[] _sharedFeatKeys =
+ [
+ "name",
+ "value",
+ ];
+
+ ///
+ /// Known keys for Slot
+ ///
+ private static readonly string[] _slotKeys =
+ [
+ "name",
+ ];
+
+ ///
+ /// Known keys for SlotOption
+ ///
+ private static readonly string[] _slotOptionKeys =
+ [
+ "default",
+ "devname",
+ "name",
+ ];
+
+ ///
+ /// Known keys for SoftwareList
+ ///
+ private static readonly string[] _softwareListKeys =
+ [
+ "filter",
+ "name",
+ "status",
+ "tag",
+ ];
+
#endregion
///
@@ -948,24 +984,12 @@ namespace SabreTools.Metadata.Filter
"rom" => _romKeys,
"sample" => _sampleKeys,
"serials" => _serialsKeys,
+ "sharedfeat" => _sharedFeatKeys,
+ "slot" => _slotKeys,
+ "slotoption" => _slotOptionKeys,
+ "softwarelist" => _softwareListKeys,
_ => null,
};
-
- // TODO: Remove this fallback path
- if (properties is null)
- {
- // Get the correct item type
- var itemType = GetDatItemType(itemName.ToLowerInvariant());
- if (itemType is null)
- return null;
-
- properties = GetProperties(itemType);
-
- // Special cases for mismatched names
- if (properties is not null && itemType == typeof(Rom))
- properties = [.. properties, "crc"];
- }
-
if (properties is null)
return null;
@@ -973,76 +997,5 @@ namespace SabreTools.Metadata.Filter
string? propertyMatch = Array.Find(properties, c => string.Equals(c, fieldName, StringComparison.OrdinalIgnoreCase));
return propertyMatch?.ToLowerInvariant();
}
-
- #region Reflection-based Helpers
-
- ///
- /// Attempt to get the DatItem type from the name
- ///
- private static Type? GetDatItemType(string? itemType)
- {
- if (string.IsNullOrEmpty(itemType))
- return null;
-
- // Loop through all loaded assemblies
- foreach (var assembly in AppDomain.CurrentDomain.GetAssemblies())
- {
- // If not all types can be loaded, use the ones that could be
- Type?[] assemblyTypes = [];
- try
- {
- assemblyTypes = assembly.GetTypes();
- }
- catch (ReflectionTypeLoadException rtle)
- {
- assemblyTypes = Array.FindAll(rtle.Types ?? [], t => t is not null);
- }
-
- // Loop through all types
- foreach (Type? type in assemblyTypes)
- {
- // If the type is invalid
- if (type is null)
- continue;
-
- // If the type isn't a class or doesn't implement the interface
- if (!type.IsClass || !typeof(DatItem).IsAssignableFrom(type))
- continue;
-
- // Get the XML type name
-#if NET20 || NET35 || NET40
- string? elementName = (Attribute.GetCustomAttribute(type, typeof(XmlRootAttribute)) as XmlRootAttribute)!.ElementName;
-#else
- string? elementName = type.GetCustomAttribute()?.ElementName;
-#endif
- if (elementName is null)
- continue;
-
- // If the name matches
- if (string.Equals(elementName, itemType, StringComparison.OrdinalIgnoreCase))
- return type;
- }
- }
-
- return null;
- }
-
- ///
- /// Get property names for the given type, if possible
- ///
- private static string[]? GetProperties(Type? type)
- {
- if (type is null)
- return null;
-
- var properties = type.GetProperties(BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.Public);
- if (properties is null)
- return null;
-
- string[] propertyNames = Array.ConvertAll(properties, f => f.Name);
- return Array.FindAll(propertyNames, s => s.Length > 0);
- }
-
- #endregion
}
}