Building class is used as a more flexible alternative to Enum (Type safe enum pattern).
I would like to be able to view the available static fields in runtime.
In my solution, each such class will have to uniformly implement the static GetAllFields () method, which I don’t really like.
Is there a more elegant solution to this problem than mine?

public abstract class ABase { protected static IEnumerable<ABase> GetAllField(Type type) { var res = from x in type.GetFields() where x.IsStatic == true where x.IsPublic == true select x.GetValue(null); ABase obj; foreach(var item in res) { if(!(item is ABase)) continue; obj = item as ABase; yield return obj; } } } public sealed class Building : ABase { public static readonly Building House = new Building(); public static readonly Building Castle = new Building(); public static System.Collections.Generic.IEnumerable<ABase> GetAllFields() { return GetAllField(typeof(Building)); } } 
  • Okay apparently, and really nothing to stir up the water here. I will do ABase.GetAllFields (typeof (Building)) at the suggestion of @VlaD - manchester
  • By the way, if your method is protected then the condition if(!(item is ABase)) will never be fulfilled. It is always false - Anton Komyshan

2 answers 2

Try this:

 public abstract class ABase { public IEnumerable<ABase> GetAllFields() { return GetType().GetFields(BindingFlags.Static) .Select(fi => fi.GetValue(null)) .Where(f => f is ABase) .Cast<ABase>(); } } 

For the static method, the trick will not work: (

  • wait, how do i call gettyp () in a static method? Type what? this does not exist. - manchester
  • @manchester: hm, yes, sorry. And really :) Now I'll think about it again. - VladD
  • @manchester: Well, how are you going to call this method? Write the desired code. - VladD
  • Hmm, I gave my decision above. it works ... Building.GetAllFields (); - manchester 1:51 pm
  • one
    Hmm, if you have one function, GetAllFields , it has nowhere to find out what it is called for the spawned class. Why not make a call in the form of ABase.GetAllFields(typeof(Building)) ? On the other hand, you are trying to do a virtual function in a static class, this is wrong. Why don't you go to instance methods and fields? And then you seem to want to make a container of objects from a static class and fields. - VladD

I would solve this problem in the following way:

 public abstract class ABase { protected static IEnumerable<ABase> GetAllField<T>() => typeof(T) .GetFields(BindingFlags.Static | BindingFlags.Public) .Select(x => x.GetValue(null)) .OfType<ABase>(); public string Name { get; protected set; } } public sealed class Building : ABase { public static readonly Building House = new Building(nameof(House)); public static readonly Building Castle = new Building(nameof(Castle)); private Building(string name) { Name = name; } public static IEnumerable<ABase> GetAllFields() => GetAllField<Building>(); } 

You can do without the Name property in ABase , then the GetAllField<T> method can return IEnumerable<string> for your example in the comments.

And in my examples, you can go through a collection like this:

 foreach (var item in Building.GetAllFields()) { Console.WriteLine(item.Name); // Ваша логика. } 

UPD: You can automate the creation of read only fields, for example:

 public abstract class ABase { protected static IEnumerable<ABase> GetAllField<T>() => typeof(T) .GetFields(BindingFlags.Static | BindingFlags.Public) .Select(x => x.GetValue(null)) .OfType<ABase>(); protected static void Init<T>() => typeof(T) .GetFields(BindingFlags.Static | BindingFlags.Public) .ToList() .ForEach(x => x.SetValue(null, Activator.CreateInstance(typeof(T), x.Name))); public string Name { get; protected set; } } public sealed class Building : ABase { public static readonly Building House; public static readonly Building Castle; public Building(string name) { Name = name; } static Building() { Init<Building>(); } public static IEnumerable<ABase> GetAllFields() => GetAllField<Building>(); } 

But I cannot but agree with VladD that it is better to switch to instance methods.