English | 简体中文 | 繁體中文 | Русский язык | Français | Español | Português | Deutsch | 日本語 | 한국어 | Italiano | بالعربية
A reflexão é a capacidade de um programa acessar, detectar e modificar seu próprio estado ou comportamento.
As assemblys contêm módulos, e os módulos contêm tipos, e os tipos contêm membros. A reflexão fornece objetos encapsulados para assemblies, módulos e tipos.
Você pode usar a reflexão para criar dinamicamente exemplos de tipos, vincular tipos a objetos existentes ou obter tipos de objetos existentes. Em seguida, você pode chamar métodos do tipo ou acessar seus campos e propriedades.
Vantagens:
1、A reflexão aumenta a flexibilidade e a expansibilidade do programa.
2、Reduz a耦合 e melhora a capacidade de adaptação.
3、Permite que o programa crie e controle objetos de qualquer classe, sem precisar prévia e codificação rígida da classe alvo.
Desvantagens:
1、Problemas de desempenho: o uso da reflexão é basicamente uma operação de interpretação, que é muito mais lenta do que o código direto ao acessar campos e métodos. Portanto, o mecanismo de reflexão é principalmente aplicado em sistemas de frameworks que exigem alta flexibilidade e escalabilidade, e não é recomendado para programas comuns.
2、A utilização da reflexão pode obscurecer a lógica interna do programa; os programadores desejam ver a lógica do programa no código-fonte, mas a reflexão desvia da técnica do código-fonte, o que pode levar a problemas de manutenção, e o código de reflexão é mais complexo do que o código direto correspondente.
A reflexão (Reflection) tem os seguintes usos:
Permite ver informações de características (attributes) no tempo de execução.
Permite examinar vários tipos na coleção e exemplificar esses tipos.
Permite a ligação atrasada de métodos e propriedades (properties).
Permite criar novos tipos no tempo de execução e executar algumas tarefas com esses tipos.
Já mencionamos em capítulos anteriores que a reflexão (Reflection) pode ser usada para verificar informações de características (attributes).
System.Reflection da classe MemberInfo O objeto precisa ser inicializado para descobrir as características relacionadas à classe. Para fazer isso, você pode definir um objeto da classe alvo, conforme abaixo:
System.Reflection.MemberInfo info = typeof(MyClass);
O seguinte programa demonstra isso:
using System; [AttributeUsage(AttributeTargets.All)] public class HelpAttribute : System.Attribute { public readonly string Url; public string Topic // Topic é um parâmetro nomeado { obter { return topic; } definir { topic = value; } } public HelpAttribute(string url) // url é um parâmetro posicional { this.Url = url; } private string topic; } [HelpAttribute("Informações sobre a classe MyClass")] class MyClass { } namespace AttributeAppl { class Program { static void Main(string[] args) { System.Reflection.MemberInfo info = typeof(MyClass); object[] attributes = info.GetCustomAttributes(true); for (int i = 0; i < attributes.Length; i++) { System.Console.WriteLine(attributes[i]); } Console.ReadKey(); } } }
Quando o código acima for compilado e executado, ele exibirá as características adicionadas à classe MyClass da característica personalizada:
HelpAttribute
Neste exemplo, utilizaremos o que foi criado no capítulo anterior DeBugInfo característica, e usa reflexão (Reflection) para ler Retângulo Metadados da classe.
using System; using System.Reflection; namespace BugFixApplication { // Uma característica personalizada BugFix é atribuída à classe e seus membros [AttributeUsage(AttributeTargets.Classe | AttributeTargets.Construtor | AttributeTargets.Field | AttributeTargets.Método | AttributeTargets.Property, PermitirMúltiplos = true)] public class DeBugInfo : System.Attribute { private int númeroDoBug; private string desenvolvedor; private string últimaRevisão; public string mensagem; public DeBugInfo(int bg, string dev, string d) { this.númeroDoBug = bg; this.desenvolvedor = dev; this.últimaRevisão = d; } public int NúmeroDoBug { obter { retornar númeroDoBug; } } public string Desenvolvedor { obter { retornar desenvolvedor; } } public string ÚltimaRevisão { obter { retornar últimaRevisão; } } public string Mensagem { obter { retornar mensagem; } definir { mensagem = valor; } } } [DeBugInfo(45, "Zara Ali", "12/8/2012" Mensagem = "Tipo de retorno não coincide")] [DeBugInfo(49, "Nuha Ali", "10/10/2012" Mensagem = "Variável não usada")] class Rectangle { // Variáveis de membro protected double comprimento; protected double largura; public Rectangle(double l, double w) { comprimento = l; largura = w; } [DeBugInfo(55, "Zara Ali", "19/10/2012" Mensagem = "Tipo de retorno não coincide")] public double GetArea()}} { return length * width; } [DeBugInfo(56, "Zara Ali", "19/10/2012) public void Display() { Console.WriteLine("Comprimento: {0}", length); Console.WriteLine("Largura: {0}", width); Console.WriteLine("Área: {0}", GetArea()); } }//fim da classe Rectangle class ExecuteRectangle { static void Main(string[] args) { Rectangle r = new Rectangle(4.5, 7.5); r.Display(); Type type = typeof(Rectangle); // Percorrendo as características da classe Rectangle foreach (Object attributes in type.GetCustomAttributes(false)) { DeBugInfo dbi = (DeBugInfo)attributes; if (null != dbi) { Console.WriteLine("Número do Bug: {0}", dbi.BugNo); Console.WriteLine("Desenvolvedor: {0}", dbi.Developer); Console.WriteLine("Última Revisão: {0}", dbi.LastReview); Console.WriteLine("Observações: {0}", dbi.Message); } } // Percorrendo as características do método foreach (MethodInfo m in type.GetMethods()) { foreach (Attribute a in m.GetCustomAttributes(true)) { DeBugInfo dbi = (DeBugInfo)a; if (null != dbi) { Console.WriteLine("Número do Bug: {0}, para Método: {1}", dbi.BugNo, m.Name); Console.WriteLine("Desenvolvedor: {0}", dbi.Developer); Console.WriteLine("Última Revisão: {0}", dbi.LastReview); Console.WriteLine("Observações: {0}", dbi.Message); } } } Console.ReadLine(); } } }
Quando o código acima for compilado e executado, ele produzirá o seguinte resultado:
Comprimento: 4.5 Largura: 7.5 Área: 33.75 Número do Bug: 49 Desenvolvedor: Nuha Ali Última Revisão: 10/10/2012 Observações: Variável não usada Número do Bug: 45 Desenvolvedor: Zara Ali Última Revisão: 12/8/2012 Observações: Descompatibilidade de tipo de retorno Número do Bug: 55, para Método: GetArea Desenvolvedor: Zara Ali Última Revisão: 19/10/2012 Observações: Descompatibilidade de tipo de retorno Número do Bug: 56, para Método: Display Desenvolvedor: Zara Ali Última Revisão: 19/10/2012 Observações: