Gostaria de saber se é possível obter atributos dos enum
valores e não do enum
próprio? Por exemplo, suponha que eu tenha o seguinte enum
:
using System.ComponentModel; // for DescriptionAttribute
enum FunkyAttributesEnum
{
[Description("Name With Spaces1")]
NameWithoutSpaces1,
[Description("Name With Spaces2")]
NameWithoutSpaces2
}
O que eu quero é dado o tipo de enumeração, produzir duas tuplas de valor de string de enumeração e sua descrição.
O valor foi fácil:
Array values = System.Enum.GetValues(typeof(FunkyAttributesEnum));
foreach (int value in values)
Tuple.Value = Enum.GetName(typeof(FunkyAttributesEnum), value);
Mas como obtenho o valor do atributo description para preencher Tuple.Desc
? Eu posso pensar em como fazê-lo se o Atributo pertencer a enum
si mesmo, mas não sei como obtê-lo a partir do valor de enum
.
c#
reflection
enums
.net-attributes
Alex K
fonte
fonte
DescriptionAttribute
.Respostas:
Isso deve fazer o que você precisa.
fonte
Esse trecho de código deve fornecer um ótimo método de extensão em qualquer enumeração que permita recuperar um atributo genérico. Acredito que seja diferente da função lambda acima, porque é mais simples de usar e um pouco - você só precisa passar no tipo genérico.
fonte
IndexOutOfRangeException
?GetCustomAttributes()
e obter o primeiro elemento em vez de chamarGetCustomAttribute()
?Esta é uma implementação genérica usando um lambda para a seleção
Chame assim:
fonte
FlagsAttribute
). Nesse caso,enumeration.GetType().GetMember(enumeration.ToString())[0]
falhará.value.GetType().GetField(value.ToString()).GetCustomAttributes(false).OfType<T>().SingleOrDefault()
mas tem que admitir que seu caminho explícito é melhor.Mesclamos algumas respostas aqui para criar uma solução um pouco mais extensível. Estou fornecendo apenas no caso de ser útil para mais alguém no futuro. Postagem original aqui .
Esta solução cria um par de métodos de extensão no Enum. O primeiro permite que você use a reflexão para recuperar qualquer atributo associado ao seu valor. A segunda chamada especificamente recupera
DescriptionAttribute
e retorna seuDescription
valor.Como exemplo, considere usar o
DescriptionAttribute
atributo deSystem.ComponentModel
Para usar o método de extensão acima, basta chamar o seguinte:
ou
fonte
Além da resposta do AdamCrawford , eu criei ainda métodos de extensão mais especializados que o alimentam para obter a descrição.
portanto, para obter a descrição, você pode usar o método de extensão original como
ou você pode simplesmente chamar o método de extensão aqui como:
O que deve tornar seu código um pouco mais legível.
fonte
Um forro fluente ...
Aqui eu estou usando o
DisplayAttribute
que contém as propriedadesName
eDescription
.Exemplo
Resultado
fonte
Aqui está o código para obter informações de um atributo Display. Ele usa um método genérico para recuperar o atributo. Se o atributo não for encontrado, ele converterá o valor de enum em uma string com pascal / camel case convertido em title case (código obtido aqui )
E este é o método de extensão para seqüências de caracteres para converter em maiúsculas e minúsculas:
fonte
Eu implementei esse método de extensão para obter a descrição dos valores de enumeração. Funciona para todos os tipos de enumerações.
fonte
Obtenha o dicionário de enum.
Agora chame isso como ...
Método Ext EnumDecription
fonte
Aqui está a versão do .NET Core da resposta de AdamCrawford, usando System.Reflection.TypeExtensions ;
fonte
Adicionando minha solução para o Net Framework e o NetCore.
Eu usei isso para minha implementação do Net Framework:
Isso não funciona para o NetCore, então eu o modifiquei para fazer isso:
Exemplo de enumeração:
Uso de amostra para estática adicionada:
fonte
Aproveitando alguns dos recursos mais recentes da linguagem C #, você pode reduzir a contagem de linhas:
fonte
Eu esta resposta para configurar uma caixa de combinação de um enum atributos que foi ótimo.
Em seguida, precisei codificar o inverso para que eu pudesse obter a seleção da caixa e retornar a enumeração no tipo correto.
Também modifiquei o código para lidar com o caso em que um atributo estava ausente
Para os benefícios da próxima pessoa, aqui está minha solução final
}
fonte
Se o seu
enum
contém um valor comoEquals
você pode encontrar alguns erros usando algumas extensões em várias respostas aqui. Isso ocorre porque normalmente é assumido quetypeof(YourEnum).GetMember(YourEnum.Value)
retornaria apenas um valor, que é oMemberInfo
seuenum
. Aqui está uma versão um pouco mais segura da resposta de Adam Crawford .fonte
Esse método de extensão obterá uma representação de seqüência de caracteres de um valor de enum usando seu XmlEnumAttribute. Se nenhum XmlEnumAttribute estiver presente, ele voltará a enum.ToString ().
fonte
E se você quiser a lista completa de nomes, pode fazer algo como
fonte
Pessoal, se ajudar, vou compartilhar com vocês minha solução: Definição do atributo Custom:
Agora, porque eu precisava dele dentro da definição HtmlHelper da extensão HtmlHelper:
Espero que ajude
fonte
Agora ele produzirá erro neste caso 1 "Igual a"
portanto, se for o mesmo nome de enum de retorno, em vez de nome de exibição, porque enumMember.GetCustomAttribute () será nulo se displayname e nome de enum forem iguais .....
fonte
Como alternativa, você pode fazer o seguinte:
fonte
Foi assim que resolvi isso sem usar extensões ou assistentes personalizados com o .NET core 3.1.
Classe
Navalha
fonte
O desempenho importa
Se você quer um melhor desempenho, este é o caminho a seguir:
Por que isso tem melhor desempenho?
Como todos os métodos internos usam código muito semelhante a esse, exceto que também executam vários outros códigos com os quais não nos importamos . O código Enum do C # é bastante horrível em geral.
O código acima foi Linq-ified e simplificado, portanto, ele contém apenas os bits com os quais nos preocupamos.
Por que o código interno é lento?
Primeiro sobre Enum.ToString () -vs- Enum.GetName (..)
Sempre use o último. (Ou melhor ainda, como ficará claro abaixo.)
ToString () usa o último internamente, mas, novamente, também faz um monte de outras coisas que não queremos, por exemplo, tenta combinar sinalizadores, imprimir números etc. Estamos interessados apenas nas constantes definidas dentro do enum.
Por sua vez, Enum.GetName obtém todos os campos, cria uma matriz de string para todos os nomes, usa o ToUInt64 acima em todos os seus RawConstantValues para criar uma matriz UInt64 de todos os valores, classifica as duas matrizes de acordo com o valor UInt64 e, finalmente, obtém o nome de a matriz de nomes fazendo um BinarySearch na matriz UInt64 para encontrar o índice do valor que desejávamos.
... e depois jogamos os campos e as matrizes classificadas para longe, use esse nome para encontrar o campo novamente.
Uma palavra: "Ugh!"
fonte
Como alternativa, você pode fazer o seguinte:
E obtenha a descrição com o seguinte:
Na minha opinião, esta é uma maneira mais eficiente de fazer o que você deseja realizar, pois nenhuma reflexão é necessária.
fonte
Você também pode definir um valor de enumeração como
Name_Without_Spaces
e, quando desejar, use uma descriçãoName_Without_Spaces.ToString().Replace('_', ' ')
para substituir os sublinhados por espaços.fonte