Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/258.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 有没有办法获取enum';使用单个字符的字符串值?_C#_Enums - Fatal编程技术网

C# 有没有办法获取enum';使用单个字符的字符串值?

C# 有没有办法获取enum';使用单个字符的字符串值?,c#,enums,C#,Enums,我在MVC应用程序中使用了一个枚举,看起来像下面的枚举 public enum School { DVB=1, AVD=2, ASB=3 } 我从每个学校的数据库中获取唯一的单个字符,例如: D for DVB A for AVD B for ASB 我想打印枚举值的全名。我可以通过以下方法实现我的目标,即编辑枚举并用字符替换枚举的整数值。但我认为这不是一个好的解决方案,因为现有代码也使用整数值 是否有其他方法可以使用单个字符获取枚举的字符串值?一个非常简单的类,用于

我在MVC应用程序中使用了一个枚举,看起来像下面的枚举

public enum School
{
    DVB=1,
    AVD=2,
    ASB=3
}
我从每个学校的数据库中获取唯一的单个字符,例如:

D for DVB
A for AVD
B for ASB
我想打印枚举值的全名。我可以通过以下方法实现我的目标,即编辑枚举并用字符替换枚举的整数值。但我认为这不是一个好的解决方案,因为现有代码也使用整数值

是否有其他方法可以使用单个字符获取枚举的字符串值?

一个非常简单的类,用于使用
[MapTo(“x”)]
属性“修饰”属性值:

[AttributeUsage(AttributeTargets.Field, AllowMultiple = false)]
public class MapToAttribute : Attribute
{
    public readonly string Key;

    public MapToAttribute(string key)
    {
        Key = key;
    }
}

public static class MapToUtilities<T> where T : struct
{
    private static readonly Dictionary<string, T> keyValues = Init();

    private static Dictionary<string, T> Init()
    {
        if (!typeof(T).IsEnum)
        {
            throw new ArgumentException(nameof(T));
        }

        var values = typeof(T).GetFields(BindingFlags.Public | BindingFlags.Static);

        var keyValues2 = new Dictionary<string, T>();

        foreach (FieldInfo fi in values)
        {
            var attr = fi.GetCustomAttribute<MapToAttribute>();
            if (attr == null)
            {
                continue;
            }

            string key = attr.Key;

            T value = (T)fi.GetValue(null);

            keyValues2.Add(key, value);
        }

        return keyValues2;
    }

    public static T KeyToValue(string key)
    {
        return keyValues[key];
    }

    public static string ValueToKey(T value)
    {
        var cmp = EqualityComparer<T>.Default;
        return keyValues.First(x => cmp.Equals(x.Value, value)).Key;
    }
}
然后:

School sc = MapToUtilities<School>.KeyToValue("A");
string key = MapToUtilities<School>.ValueToKey(sc);
School sc=MapToUtilities.KeyToValue(“A”);
字符串键=MapToUtilities.ValueToKey(sc);
一个非常简单的类,用于使用
[MapTo(“x”)]
属性“装饰”属性值:

[AttributeUsage(AttributeTargets.Field, AllowMultiple = false)]
public class MapToAttribute : Attribute
{
    public readonly string Key;

    public MapToAttribute(string key)
    {
        Key = key;
    }
}

public static class MapToUtilities<T> where T : struct
{
    private static readonly Dictionary<string, T> keyValues = Init();

    private static Dictionary<string, T> Init()
    {
        if (!typeof(T).IsEnum)
        {
            throw new ArgumentException(nameof(T));
        }

        var values = typeof(T).GetFields(BindingFlags.Public | BindingFlags.Static);

        var keyValues2 = new Dictionary<string, T>();

        foreach (FieldInfo fi in values)
        {
            var attr = fi.GetCustomAttribute<MapToAttribute>();
            if (attr == null)
            {
                continue;
            }

            string key = attr.Key;

            T value = (T)fi.GetValue(null);

            keyValues2.Add(key, value);
        }

        return keyValues2;
    }

    public static T KeyToValue(string key)
    {
        return keyValues[key];
    }

    public static string ValueToKey(T value)
    {
        var cmp = EqualityComparer<T>.Default;
        return keyValues.First(x => cmp.Equals(x.Value, value)).Key;
    }
}
然后:

School sc = MapToUtilities<School>.KeyToValue("A");
string key = MapToUtilities<School>.ValueToKey(sc);
School sc=MapToUtilities.KeyToValue(“A”);
字符串键=MapToUtilities.ValueToKey(sc);

实现这一点的方法有很多。一个非常简单的选择是使用第二个枚举和值的可选ID;e、 g

void Main()
{
    Console.WriteLine((School)Enum.Parse(typeof(ConvertSchool),"A"));
}
public enum School
{
    DVB=1,
    AVD=2,
    ASB=3
}
public enum ConvertSchool
{
    D =1,
    A =2,
    B =3
}

更好的方法是创建某种映射;e、 g.使用字典将每个字符键映射到相关的学校值:

public enum School
{
    DVB=1,
    AVD=2,
    ASB=3
}
readonly IDictionary SchoolMap = new Dictionary<char,School>() {
    {'D', School.DVB},
    {'A', School.AVD},
    {'B', School.ASB}
};
void Main()
{
    Console.WriteLine(SchoolMap['A']);
}
在最后一个示例中,如果传递的字符没有对应的学校(例如,
Console.WriteLine((学校)'X');
),您将得到一个
无效操作异常。如果您不希望此处出现错误,而是希望接收
null
值,请将每个隐式转换语句中的
First
替换为
FirstOrDefault


另一种解决方案是将映射保存在数据库层中;创建具有映射值的表,甚至在视图的定义中保存这些映射;然后使用表上的视图连接到映射以检索每个学校的3字符代码,而不是1字符代码;e、 g

--if you have a SchoolMap table relating the 1 char code to the 3 char code:

create table SchoolMap 
(
    Char1Code nchar(1) not null primary key clustered
    , Char3Code nvarchar(3) not null unique
)

create view SchoolView as 
select School.*
, SchoolMap.Char3Code
from School
left outer join SchoolMap 
on SchoolMap.Char1Code = School.Code 


--if you don't have and don't want a table holding the mapping, you can do the same in the view's definition:

create view SchoolView as 
select School.*
, SchoolMap.Char3Code
from School
left outer join 
(
    values ('D','DVB'),('A','AVD'),('B','ASB')
) SchoolMap (Char1Code, Char3Code)
on SchoolMap.Char1Code = School.Code 

有很多方法可以实现这一点。一个非常简单的选择是使用第二个枚举和值的可选ID;e、 g

void Main()
{
    Console.WriteLine((School)Enum.Parse(typeof(ConvertSchool),"A"));
}
public enum School
{
    DVB=1,
    AVD=2,
    ASB=3
}
public enum ConvertSchool
{
    D =1,
    A =2,
    B =3
}

更好的方法是创建某种映射;e、 g.使用字典将每个字符键映射到相关的学校值:

public enum School
{
    DVB=1,
    AVD=2,
    ASB=3
}
readonly IDictionary SchoolMap = new Dictionary<char,School>() {
    {'D', School.DVB},
    {'A', School.AVD},
    {'B', School.ASB}
};
void Main()
{
    Console.WriteLine(SchoolMap['A']);
}
在最后一个示例中,如果传递的字符没有对应的学校(例如,
Console.WriteLine((学校)'X');
),您将得到一个
无效操作异常。如果您不希望此处出现错误,而是希望接收
null
值,请将每个隐式转换语句中的
First
替换为
FirstOrDefault


另一种解决方案是将映射保存在数据库层中;创建具有映射值的表,甚至在视图的定义中保存这些映射;然后使用表上的视图连接到映射以检索每个学校的3字符代码,而不是1字符代码;e、 g

--if you have a SchoolMap table relating the 1 char code to the 3 char code:

create table SchoolMap 
(
    Char1Code nchar(1) not null primary key clustered
    , Char3Code nvarchar(3) not null unique
)

create view SchoolView as 
select School.*
, SchoolMap.Char3Code
from School
left outer join SchoolMap 
on SchoolMap.Char1Code = School.Code 


--if you don't have and don't want a table holding the mapping, you can do the same in the view's definition:

create view SchoolView as 
select School.*
, SchoolMap.Char3Code
from School
left outer join 
(
    values ('D','DVB'),('A','AVD'),('B','ASB')
) SchoolMap (Char1Code, Char3Code)
on SchoolMap.Char1Code = School.Code 

最干净的方法是与您的团队坐在一起计划并接受迁移数据库并存储整数值

无论如何,根据您在问题中的评论,您正在使用实体框架并将实体映射到视图模型。以下步骤可以帮助您在不进行反射的情况下添加新属性或新枚举

假设您正在使用一个名为
MyEntity
的实体,它实际上包含一个名为
MySchool
的属性

首先,不要对类型
MySchool
属性使用
School
枚举,而只使用字符串类型。所以EF只需从数据库中检索数据并将其直接放入属性。不需要转换。所以你会有这样的东西:

public class MyEntity
{
    public string MySchool { get; set; }
}
其次,始终在您的
MyEntity
类中添加另一个属性,将其命名为
MySchoolEnum
,该属性的类型将为
School
enum,并且不会映射到数据库,因此您有:

[NotMapped] // <-- This tell EF that this property is not mapped to the database.
public School? MyShcoolEnum
{
    get
    {
        // Getting the value of this property depends on the value of the database
        // which is stored into MySchool property.
        switch (MySchool)
        {
            case "D": return School.DVB;
            case "A": return School.AVD;
            case "B": return School.ASB;
            default: return null;
        }
    }

    set
    {
        // When setting this property 
        // you automatically update the value of MySchool property
        switch (value)
        {
            case School.DVB: this.MySchool = "D";
                break;
            case School.AVD: this.MySchool = "A";
                break;
            case School.ASB: this.MySchool = "B";
                break;
            default: this.MySchool = null;
                break;
        }
    }
}

最干净的方法是与您的团队坐在一起计划并接受迁移数据库并存储整数值

无论如何,根据您在问题中的评论,您正在使用实体框架并将实体映射到视图模型。以下步骤可以帮助您在不进行反射的情况下添加新属性或新枚举

假设您正在使用一个名为
MyEntity
的实体,它实际上包含一个名为
MySchool
的属性

首先,不要对类型
MySchool
属性使用
School
枚举,而只使用字符串类型。所以EF只需从数据库中检索数据并将其直接放入属性。不需要转换。所以你会有这样的东西:

public class MyEntity
{
    public string MySchool { get; set; }
}
其次,始终在您的
MyEntity
类中添加另一个属性,将其命名为
MySchoolEnum
,该属性的类型将为
School
enum,并且不会映射到数据库,因此您有:

[NotMapped] // <-- This tell EF that this property is not mapped to the database.
public School? MyShcoolEnum
{
    get
    {
        // Getting the value of this property depends on the value of the database
        // which is stored into MySchool property.
        switch (MySchool)
        {
            case "D": return School.DVB;
            case "A": return School.AVD;
            case "B": return School.ASB;
            default: return null;
        }
    }

    set
    {
        // When setting this property 
        // you automatically update the value of MySchool property
        switch (value)
        {
            case School.DVB: this.MySchool = "D";
                break;
            case School.AVD: this.MySchool = "A";
                break;
            case School.ASB: this.MySchool = "B";
                break;
            default: this.MySchool = null;
                break;
        }
    }
}

这感觉像是一个糟糕透顶的方法。为什么不使用对象呢?那么如果存储
A
,会发生什么呢?有两个项目以
A
开头,如果以后要添加新学校,该怎么办?您是否要为此重写整个代码?为什么不将枚举值(作为整数)存储在数据库中?这样你就不会被不同的性格所误导。你可以很容易地把一个整数解析成一个枚举值。我喜欢早上XY的味道。这感觉像是一个糟糕透顶的方法。为什么不使用对象呢?那么如果存储
A
,会发生什么呢?有两个项目以
A
开头,如果以后要添加新学校,该怎么办?您是否要为此重写整个代码?为什么不将枚举值(作为整数)存储在数据库中?这样你就不会被不同的性格所误导。您可以非常轻松地将整数解析为枚举值我喜欢早上XY的味道这种方法唯一的问题是执行查询的自然方式是从db.Context.MyTable中的x进行
,其中