É possível adicionar atributos no tempo de execução ou alterar o valor de um atributo no tempo de execução?
É possível adicionar atributos no tempo de execução ou alterar o valor de um atributo no tempo de execução?
Respostas:
Atributos são metadados estáticos. Assemblies, módulos, tipos, membros, parâmetros e valores de retorno não são objetos de primeira classe em C # (por exemplo, a System.Type
classe é apenas uma representação refletida de um tipo). Você pode obter uma instância de um atributo para um tipo e alterar as propriedades se elas forem graváveis, mas isso não afetará o atributo conforme é aplicado ao tipo.
Isso realmente depende do que exatamente você está tentando realizar.
O material System.ComponentModel.TypeDescriptor pode ser usado para adicionar atributos a tipos, propriedades e instâncias de objetos e tem a limitação de que você deve usá-lo para recuperar essas propriedades também. Se você está escrevendo o código que consome esses atributos e pode viver dentro dessas limitações, eu definitivamente o sugeriria.
Até onde eu sei, o controle PropertyGrid e a superfície de design do visual studio são as únicas coisas na BCL que consomem o material TypeDescriptor. De fato, é assim que eles fazem cerca da metade das coisas que realmente precisam fazer.
TypeDescriptor
e TypeDescriptionProvider
não são implementados?
[Attr(1), Attr(2), Attr(3)]
Apenas ex Attr(3)
é encontrado.
Bem, só para ser diferente, encontrei um artigo que faz referência ao Reflection.Emit para fazer isso.
Aqui está o link: http://www.codeproject.com/KB/cs/dotnetattributes.aspx , você também deseja examinar alguns dos comentários na parte inferior do artigo, porque abordagens possíveis são discutidas.
YourClass
em YourRuntimeClassWithAttributes
.
YourClass
, poderá subclassificá-lo em tempo de execução e gerar uma classe idêntica com um nome ligeiramente diferente que também tenha os atributos criados dinamicamente desejados, e o polimorfismo permitirá que o código de verificação de tipo ainda identifique sua classe básica.
Não, não é.
Os atributos são metadados e armazenados em formato binário no assembly compilado (é também por isso que você só pode usar tipos simples).
Eu não acredito nisso. Mesmo se eu estiver errado, o melhor que você pode esperar é adicioná-los a um Type inteiro, nunca a uma instância de um Type.
Se você precisar de algo para poder adicionar dinamicamente, os atributos c # não são o caminho. Procure armazenar os dados em xml. Recentemente, eu fiz um projeto que iniciei com atributos, mas que acabei mudando para serialização com xml.
Por que você precisa? Os atributos fornecem informações extras para reflexão, mas se você souber externamente quais propriedades deseja, não precisará delas.
Você pode armazenar metadados externamente com relativa facilidade em um banco de dados ou arquivo de recurso.
Eu tentei muito com System.ComponentModel.TypeDescriptor sem sucesso. Isso não significa que não pode funcionar, mas eu gostaria de ver o código para isso.
Em contrapartida, eu queria alterar alguns valores de atributo. Eu fiz duas funções que funcionam bem para esse fim.
// ************************************************************************
public static void SetObjectPropertyDescription(this Type typeOfObject, string propertyName, string description)
{
PropertyDescriptor pd = TypeDescriptor.GetProperties(typeOfObject)[propertyName];
var att = pd.Attributes[typeof(DescriptionAttribute)] as DescriptionAttribute;
if (att != null)
{
var fieldDescription = att.GetType().GetField("description", BindingFlags.NonPublic | BindingFlags.Instance);
if (fieldDescription != null)
{
fieldDescription.SetValue(att, description);
}
}
}
// ************************************************************************
public static void SetPropertyAttributReadOnly(this Type typeOfObject, string propertyName, bool isReadOnly)
{
PropertyDescriptor pd = TypeDescriptor.GetProperties(typeOfObject)[propertyName];
var att = pd.Attributes[typeof(ReadOnlyAttribute)] as ReadOnlyAttribute;
if (att != null)
{
var fieldDescription = att.GetType().GetField("isReadOnly", BindingFlags.NonPublic | BindingFlags.Instance);
if (fieldDescription != null)
{
fieldDescription.SetValue(att, isReadOnly);
}
}
}
Em Java, eu costumava contornar isso usando um mapa e implementando minha própria abordagem na codificação de valor-chave.
http://developer.apple.com/documentation/Cocoa/Conceptual/KeyValueCoding/KeyValueCoding.html
TypeDescriptor
- não apenasPropertyGrid
.