我成功修改了@plinth发布的代码
[AttributeUsage(AttributeTargets.Field,
AllowMultiple = true)]
public class SubcategoryOf : Attribute
{
public Enum? Category { get; }
public SubcategoryOf(object category)
{
if (category is Enum categoryEnum) Category = categoryEnum;
}
}
public static class CategoryExtension
{
public static bool IsSubcategoryOf(this Enum subcategory,
Enum category)
{
var t = subcategory.GetType();
/*This section is for returning true if enum is
of the same category (eg. Product.Fruit is Product.Fruit) */
if (Equals(subcategory,
category))
return true;
var memberInfo = t.GetMember(subcategory.ToString());
/*This section loops through all attributes for a match of
declared category and returns its result true/false */
foreach (var member in memberInfo)
if (member.IsDefined(typeof(SubcategoryOf)))
return member.GetCustomAttributes(typeof(SubcategoryOf))
.Cast<SubcategoryOf?>()
.Any(subCatOf => Equals(subCatOf!.Category,
category));
/*If a category is not assigned a warning is posted to the
debug console that an attempt to compare an enum without a
category was made and returns false, this does not stop the
program with a throw exception as this should not break the
intended use of comparing.*/
Debug.WriteLine($"the enum {subcategory} does not contain a category and was being compared.",
"Warning(CategoryExtension.IsSubcategoryOf)");
return false;
}
}
以下是使用上述类的示例:
public enum Proficiency
{
ArmorProficiency,
WeaponProficiency,
ToolProficiency,
LanguageProficiency
}
public enum ArmorProficiency
{
[IsSubcategoryOf(Proficiency.ArmorProficiency)]
Light,
[IsSubcategoryOf(Proficiency.ArmorProficiency)]
Medium,
[IsSubcategoryOf(Proficiency.ArmorProficiency)]
Heavy,
[IsSubcategoryOf(Proficiency.ArmorProficiency)]
Shield,
}
public enum LightArmorProficiency
{
[IsSubcategoryOf(ArmorProficiency.Light)]
[IsSubcategoryOf(Proficiency.ArmorProficiency)]
PaddedArmor,
[IsSubcategoryOf(ArmorProficiency.Light)]
[IsSubcategoryOf(Proficiency.ArmorProficiency)]
LeatherArmor,
[IsSubcategoryOf(ArmorProficiency.Light)]
[IsSubcategoryOf(Proficiency.ArmorProficiency)]
StuddedLeatherArmor,
}
public enum HeavyArmorProficiency
{
[IsSubcategoryOf(ArmorProficiency.Heavy)]
[IsSubcategoryOf(Proficiency.ArmorProficiency)]
RingMail,
[IsSubcategoryOf(ArmorProficiency.Heavy)]
[IsSubcategoryOf(Proficiency.ArmorProficiency)]
ChainMail,
[IsSubcategoryOf(ArmorProficiency.Heavy)]
[IsSubcategoryOf(Proficiency.ArmorProficiency)]
SplintMail,
[IsSubcategoryOf(ArmorProficiency.Heavy)]
[IsSubcategoryOf(Proficiency.ArmorProficiency)]
PlateMail,
}
以下是一个使用枚举类和分类类的示例。
public class Proficiencies
{
private readonly Dictionary<Enum, ProficiencyType> _armorProficiencies;
private readonly Dictionary<Enum, ProficiencyType> _weaponProficiencies;
private readonly Dictionary<Enum, ProficiencyType> _toolProficiencies;
private readonly Dictionary<Enum, LanguageComprehension> _languageProficiencies;
public IReadOnlyDictionary<Enum, ProficiencyType> ArmorProficiencies =>
_armorProficiencies;
public IReadOnlyDictionary<Enum, ProficiencyType> WeaponProficiencies =>
_weaponProficiencies;
public IReadOnlyDictionary<Enum, ProficiencyType> ToolProficiencies =>
_toolProficiencies;
public IReadOnlyDictionary<Enum, LanguageComprehension> LanguageProficiencies =>
_languageProficiencies;
public Proficiencies(bool startsWithCommon,
LanguageComprehension comprehensionLevel = LanguageComprehension.ReadAndWrite)
{
_armorProficiencies = new Dictionary<Enum, ProficiencyType>();
_weaponProficiencies = new Dictionary<Enum, ProficiencyType>();
_toolProficiencies = new Dictionary<Enum, ProficiencyType>();
_languageProficiencies = new Dictionary<Enum, LanguageComprehension>();
if (startsWithCommon)
_languageProficiencies.Add(StandardLanguageProficiency.Common,
comprehensionLevel);
}
public void AddNonLanguageProficiency(Enum proficiency,
ProficiencyType proficiencyType)
{
if (proficiency.IsSubcategoryOf(Proficiency.ArmorProficiency))
{
if (_armorProficiencies.ContainsKey(proficiency))
_armorProficiencies[proficiency] = proficiencyType;
else
_armorProficiencies.Add(proficiency,
proficiencyType);
}
else if (proficiency.IsSubcategoryOf(Proficiency.WeaponProficiency))
{
if (_weaponProficiencies.ContainsKey(proficiency))
_weaponProficiencies[proficiency] = proficiencyType;
else
_weaponProficiencies.Add(proficiency,
proficiencyType);
}
else if (proficiency.IsSubcategoryOf(Proficiency.ToolProficiency))
{
if (_toolProficiencies.ContainsKey(proficiency))
_toolProficiencies[proficiency] = proficiencyType;
else
_toolProficiencies.Add(proficiency,
proficiencyType);
}
else
{
Debug.WriteLine($"The enum {proficiency} is not a valid proficiency and was being added.",
"Warning(Proficiencies.AddProficiency)");
}
}
public void RemoveProficiency(Enum proficiency)
{
if ( _armorProficiencies.ContainsKey(proficiency) )
_armorProficiencies.Remove(proficiency);
else if ( _weaponProficiencies.ContainsKey(proficiency) )
_weaponProficiencies.Remove(proficiency);
else if ( _toolProficiencies.ContainsKey(proficiency) )
_toolProficiencies.Remove(proficiency);
else if ( _languageProficiencies.ContainsKey(proficiency))
_languageProficiencies.Remove(proficiency);
}
public void AddLanguageProficiency(Enum language,
LanguageComprehension comprehension)
{
if (!language.IsSubcategoryOf(Proficiency.LanguageProficiency)) return;
if (_languageProficiencies.ContainsKey(language))
_languageProficiencies[language] = comprehension;
else
_languageProficiencies.Add(language,
comprehension);
}
}
摘要:
在这种情况下,主要类别现在由提供的枚举定义,而不是硬编码。subcategoryOf类不关心给定的内容,只要它是对象类型的枚举。
扩展类现在仅检查子类别是否属于类别或其他类别的属性,并且不硬编码枚举类型。这反过来允许使用多个枚举集合,而无需将所有内容强制转换为单个枚举,如果子类别不属于它,它将返回false。
enum Cats{ Fruit_Apple, Fruit_Pear }
- Philip Pittle