简体   繁体   中英

Cast static readonly property from id

I have the following class:

public sealed class TaskType
{
    private readonly String name;
    private readonly int value;

    public static readonly TaskType BUG = new TaskType(1, "Bug");
    public static readonly TaskType ISSUE = new TaskType(2, "Issue");
    public static readonly TaskType FEATURE = new TaskType(3, "Feature");
    //more here

    private TaskType(int value, String name)
    {
        this.name = name;
        this.value = value;
    }

    public override string ToString()
    {
        return name;
    }
}

How can I cast TaskType from say a value:

int i = 1;
String name = (TaskType)i.ToString(); // this is where i am stuck!

I know I have to use Reflection to iterate through the properties, but this not working for me.

i have tried to use this function for example, but this doesn't work:

private TaskType getTaskType(int id)
{
    PropertyInfo[] properties = typeof(TaskType).GetProperties(BindingFlags.Public | BindingFlags.Static);

    foreach (PropertyInfo property in properties)
    {
        TaskType t = (TaskType)property.GetValue(null, null);
        if (t.ToValue() == id)
            return t;
    }

    return null;
}

Why don't you just use an Enum type?

public enum Task {
  Bug,
  Issue,
  Feature
}

Then you can cast it from an int.

int i = 1;
Task myTask = (Task)i;

You can also get it from the string name.

string s = "Bug";
Task bugType = Enum.Parse(typeof(Task), s);

The problem is that you are trying to get properties but your TaskType objects are fields:

public static TaskType GetTaskType(int id)
{
    FieldInfo[] fields = typeof(TaskType).GetFields(BindingFlags.Public | BindingFlags.Static);

    foreach (FieldInfo field in fields)
    {
        TaskType t = (TaskType)field.GetValue(null);
        if (t.value == id)
        {
            return t;
        }
    }

    return null;
}

Using LINQ this can be a single line of code:

public static TaskType GetTaskType(int id)
{
    return typeof(TaskType)
        .GetFields(BindingFlags.Public | BindingFlags.Static)
        .Select(f => (f.GetValue(null) as TaskType))
        .FirstOrDefault(t => t != null && t.value == id);
}

public static TaskType GetTaskType(string name)
{
    return typeof(TaskType)
        .GetFields(BindingFlags.Public | BindingFlags.Static)
        .Select(f => (f.GetValue(null) as TaskType))
        .FirstOrDefault(
            t => t != null &&
            t.name.Equals(name, StringComparison.InvariantCultureIgnoreCase));
}

However, as others already mentioned an enum might be much easier.

If you really stuck with that class definition and cannot use something like enum, then here is working code, which gets name via reflection:

int id = 1;
Type type = typeof(TaskType);
BindingFlags privateInstance = BindingFlags.NonPublic | BindingFlags.Instance;
var name = type
    .GetFields(BindingFlags.Public | BindingFlags.Static)
    .Select(p => p.GetValue(null))
    .Cast<TaskType>()
    .Where(t => (int)type.GetField("value", privateInstance).GetValue(t) == id)
    .Select(t => (string)type.GetField("name", privateInstance).GetValue(t))
    .FirstOrDefault();

// Output: Bug

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM