C# 从id强制转换静态只读属性

C# 从id强制转换静态只读属性,c#,static-members,C#,Static Members,我有以下课程: 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"); publ

我有以下课程:

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;
    }
}
如何从值中强制转换TaskType:

int i = 1;
String name = (TaskType)i.ToString(); // this is where i am stuck!
我知道我必须使用反射来迭代属性,但这对我不起作用

例如,我曾尝试使用此函数,但不起作用:

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;
}

为什么不使用枚举类型呢

public enum Task {
  Bug,
  Issue,
  Feature
}
然后你可以从一个int中转换它

int i = 1;
Task myTask = (Task)i;
您还可以从字符串名称中获取它

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

为什么不使用枚举类型呢

public enum Task {
  Bug,
  Issue,
  Feature
}
然后你可以从一个int中转换它

int i = 1;
Task myTask = (Task)i;
您还可以从字符串名称中获取它

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

如果您确实坚持使用该类定义,并且无法使用类似于enum的东西,那么下面是工作代码,它通过反射获取名称:

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

如果您确实坚持使用该类定义,并且无法使用类似于enum的东西,那么下面是工作代码,它通过反射获取名称:

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

问题是您试图获取属性,但TaskType对象是字段:

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;
}
使用LINQ,这可以是一行代码:

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));
}

但是,正如其他人已经提到的那样,枚举可能要容易得多。

问题是您试图获取属性,但TaskType对象是字段:

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;
}
使用LINQ,这可以是一行代码:

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));
}

但是,正如其他人已经提到的,枚举可能更容易。

i是integer类型,不能强制转换为TaskType类型。如果TaskType有一个静态集合,一个数组或各种静态只读实例的字典,您的目标可能会更简单。但我感觉你可能正在冒险进入代码气味领域。这非常令人困惑。我想你需要的是??。。此外,这可以通过枚举来解决,您知道…i是integer类型,不能强制转换为TaskType类型如果TaskType有一个静态集合,一个数组或各种静态只读实例的字典,您的目标可能会更简单。但我感觉你可能正在冒险进入代码气味领域。这非常令人困惑。我想你需要的是??。。而且,这可以通过枚举来解决,你知道。。。。。。因为这不涉及反射的缓慢性和大量的公共静态只读实例(无论什么实例都会无缘无故地消耗内存)。很抱歉,我移动到此类型,因为我需要enum未提供的额外功能。实际的TaskType类更复杂,并且具有其他属性。另外,我必须使用现有的代码,这对枚举来说不是很好。。。。因为这不涉及反射的缓慢性和大量的公共静态只读实例(无论什么实例都会无缘无故地消耗内存)。很抱歉,我移动到此类型,因为我需要enum未提供的额外功能。实际的TaskType类更复杂,并且具有其他属性。另外,我必须使用现有的代码,这对Enum不是很好。非常感谢。我会有一点偏见,把这个作为答案,因为它帮助我回答了另一个问题,我想问的是,把列表作为下拉列表-这对我来说至少是用上面的解决方案更容易解决的问题。非常感谢。将有点偏见,并将此设置为答案,因为这有助于我回答另一个问题,我要问的是作为下拉列表获取列表-现在这对我来说至少更容易使用上述解决方案。非常感谢pescolino!非常感谢佩斯科利诺!