Eu tenho um bloco de código que serializa um tipo em uma marca de HTML.
Type t = typeof(T); // I pass <T> in as a paramter, where myObj is of type T
tagBuilder.Attributes.Add("class", t.Name);
foreach (PropertyInfo prop in t.GetProperties())
{
object propValue = prop.GetValue(myObj, null);
string stringValue = propValue != null ? propValue.ToString() : String.Empty;
tagBuilder.Attributes.Add(prop.Name, stringValue);
}
Isso funciona muito bem, exceto eu quero apenas fazer isso para tipos primitivos, como int
, double
, bool
etc, e outros tipos que não são primitivos, mas pode ser serializado facilmente como string
. Quero que ele ignore todo o resto, como Listas e outros tipos personalizados.
Alguém pode sugerir como eu faço isso? Ou preciso especificar os tipos que quero permitir em algum lugar e ativar o tipo da propriedade para ver se é permitido? Isso é um pouco confuso, então seria bom se eu tivesse uma maneira mais organizada.
c#
reflection
primitive-types
DaveDev
fonte
fonte
System.String
não é um tipo primitivo.Respostas:
Você pode usar a propriedade
Type.IsPrimitive
, mas tenha cuidado, porque existem alguns tipos que podemos pensar que são primitivos, mas eles não são, por exemplo,Decimal
eString
.Editar 1: código de amostra adicionado
Aqui está um código de exemplo:
Edit 2: Como o @SLaks comenta, existem outros tipos que talvez você queira tratar como primitivos também. Eu acho que você terá que adicionar essas variações uma a uma .
Edit 3: IsPrimitive = (Booleano, Byte, SByte, Int16, UInt16, Int32, UInt32, Int64, UInt64, IntPtr, UIntPtr, Char, Double e Single), tipo Anther Primitive-Like para verificar (t == typeof (DateTime )))
fonte
DateTime
,TimeSpan
eDateTimeOffset
.||
), não o bit a bit ou (|
).Acabei de encontrar esta pergunta ao procurar uma solução semelhante e pensei que você poderia estar interessado na seguinte abordagem usando
System.TypeCode
eSystem.Convert
.É fácil serializar qualquer tipo mapeado para
System.TypeCode
outro que não sejaSystem.TypeCode.Object
, para que você possa fazer:A vantagem dessa abordagem é que você não precisa nomear todos os outros tipos não primitivos aceitáveis. Você também pode modificar um pouco o código acima para manipular qualquer tipo que implemente IConvertible.
fonte
Guid
para meus próprios propósitos (como um primitivo na minha definição).Fazemos assim em nosso ORM:
Eu sei que usar
IsValueType
não é a melhor opção (você pode ter suas próprias estruturas muito complexas), mas funciona em 99% dos casos (e inclui Nullables).fonte
decimal
nesse sentido. Mas existe um tipo para o qualIsPrimitive
retornatrue
masIsValueType
retornafalse
? Se não houver esse tipo, ot.IsPrimitive
teste será desnecessário.IsValueType
configurado como true, portanto,IsPrimitive
não é necessário procurar . Felicidades!A partir da resposta de @Ronnie Overby e do comentário de @jonathanconway, escrevi este método que funciona com o Nullable e exclui as estruturas do usuário.
Com o seguinte TestCase:
fonte
Enum
não é suportada, teste-a comenum MyEnum { EnumValue }
e usandoMyEnum
. @ Jonathan também está usandotype.IsValueType
. Com isso, osEnums
são detectados corretamente, mas tambémStructs
. Portanto, cuidado com os primitivos que você deseja.type.IsValueType
, por que simplesmente não adicionartype.IsEnum
?type.IsEnum
também é possível. Eu sugeri uma edição no seu post :)Aqui está como eu fiz isso.
fonte
IsAssignableFrom
em seu teste em vez de conter?Também uma boa possibilidade:
fonte
Type
possui uma propriedade chamada IsPrimitive . Você deveria usar isso.String
nemDecimal
são primitivos.Supondo que você tenha uma assinatura de função como esta:
Você pode adicionar uma restrição genérica para permitir apenas tipos de valor:
Observe que isso permite não apenas tipos primitivos para T, mas qualquer tipo de valor.
fonte
Eu precisava serializar tipos para exportá-los para XML. Para fazer isso, eu iterava pelo objeto e optei por campos que eram primitivos, enum, tipos de valor ou serializáveis. Este foi o resultado da minha consulta:
Usei o LINQ para percorrer os tipos e obter seu nome e valor para armazenar em uma tabela de símbolos. A chave está na cláusula 'where' que escolhi para reflexão. Eu escolhi tipos primitivos, enumerados, de valor e tipos serializáveis. Isso permitiu que strings e objetos DateTime passassem como eu esperava.
Felicidades!
fonte
É isso que tenho na minha biblioteca. Comentários são bem-vindos.
Verifico IsValueType primeiro, pois ele lida com a maioria dos tipos, depois String, uma vez que é o segundo mais comum. Não consigo pensar em um primitivo que não seja um tipo de valor, então não sei se essa parte do objeto foi atingida.
Então eu posso usá-lo assim:
fonte
Eu só quero compartilhar minha solução. Talvez seja útil para qualquer pessoa.
fonte
IsPrimitiveType(typeof(System.AccessViolationException)) == true
namespace System { class MyNonPrimitiveType { } }
Não se esqueça de verificar o espaço para nome NULL, porque objetos anônimos não possuem espaço para nome atribuído
fonte
Aqui está outra opção viável.
fonte