C # reflexão: Localizando atributos em um campo de membro
-
03-07-2019 - |
Pergunta
Eu pode estar perguntando isso incorretamente, mas pode / como você pode encontrar campos em uma classe em si ... por exemplo ...
public class HtmlPart {
public void Render() {
//this.GetType().GetCustomAttributes(typeof(OptionalAttribute), false);
}
}
public class HtmlForm {
private HtmlPart _FirstPart = new HtmlPart();
[Optional] //<-- how do I find that?
private HtmlPart _SecondPart = new HtmlPart();
}
Ou talvez eu só estou fazendo isso incorretamente ... Como posso chamar um método e, em seguida, verificar se há atributos aplicados a si?
Além disso, por causa da questão - Só estou curioso se era possível encontrar informações de atributo sem saber / acessar a classe pai
Solução
Se eu entendi sua pergunta, acho que o que você está tentando fazer não é possível ...
No método Render
, você deseja obter um atributo possível aplicado ao objeto. O atributo pertence à bruxa campo _SecondPart
pertence à HtmlForm
classe.
Para que isso funcione, você teria que passar o objeto de chamada para o método Render
:
public class HtmlPart {
public void Render(object obj) {
FieldInfo[] infos = obj.GetType().GetFields(BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance);
foreach (var fi in infos)
{
if (fi.GetValue(obj) == this && fi.IsDefined(typeof(OptionalAttribute), true))
Console.WriteLine("Optional is Defined");
}
}
}
Outras dicas
Aqui está um exemplo de dado um único objeto como encontrar se houver pública ou áreas privadas nesse objeto tem uma propriedade específica:
var type = typeof(MyObject);
foreach (var field in type.GetFields(BindingFlags.Public |
BindingFlags.NonPublic | BindingFlags.Instance))
{
if (field.IsDefined(typeof(ObsoleteAttribute), true))
{
Console.WriteLine(field.Name);
}
}
Para a segunda parte da sua pergunta, você pode verificar se um atributo é defiend no método atual usando:
MethodInfo.GetCurrentMethod().IsDefined(typeof(ObsoleteAttribute));
Editar
Para responder às suas editar sim é possível sem saber o tipo real. A função a seguir leva um tipo de parâmetro e retorna todos os campos que possuem um determinado atributo. Alguém em algum lugar vai quer saber o tipo que você deseja pesquisar, ou terá uma instância do tipo que você deseja pesquisar.
Sem isso você teria que fazer como Jon Skeet disse que é para enumerar todos os objetos em uma montagem.
public List<FieldInfo> FindFields(Type type, Type attribute)
{
var fields = new List<FieldInfo>();
foreach (var field in type.GetFields(BindingFlags.Public |
BindingFlags.NonPublic |
BindingFlags.Instance))
{
if (field.IsDefined(attribute, true))
{
fields.Add(field);
}
}
return fields;
}
Você pode encontrar campos dentro de uma classe usando Type.GetFields
, e você pode encontrar atributos aplicada a um campo usando MemberInfo.GetCustomAttributes
ou IsDefined
- mas se você precisa encontrar todos os campos de um determinado tipo, você vai ter que:
- iterar sobre todos os conjuntos que você deseja pesquisar
- iterar sobre todos os tipos dentro de cada montagem
- iterar sobre todos os campos dentro de cada tipo
- Verifique se o atributo de presença / ausência para cada campo
Agora, se você está realmente tentando descobrir "é um atributo específico aplicado a um campo cujo valor é uma referência a 'isto' objeto", então isso é ainda mais difícil - porque você teria que saber tudo sobre cada objeto no sistema. Você também deve ter em mente que poderia haver dois Campos ambos com o mesmo valor, ou seja, referenciando o mesmo objeto. Será que a contagem de objeto como "opcional", nesse caso, ou não?
Basicamente, se o objeto deve ter uma propriedade (por exemplo, opcional ou não), então, que deve ser uma propriedade do objeto em si, e não o campo que contém a propriedade.
Pode ser que eu estou interpretando mal o que você está tentando fazer, mas eu suspeito não é tanto viável ou pelo menos não uma boa idéia. Você poderia explicar a foto maior aqui? O que você está realmente tentando alcançar com este atributo?