Há um grupo de métodos particulares na minha classe e preciso chamar um dinamicamente com base em um valor de entrada. O código de chamada e os métodos de destino estão na mesma instância. O código fica assim:
MethodInfo dynMethod = this.GetType().GetMethod("Draw_" + itemType);
dynMethod.Invoke(this, new object[] { methodParams });
Nesse caso, GetMethod()
não retornará métodos privados. O BindingFlags
que eu preciso fornecer para GetMethod()
que ele possa localizar métodos particulares?
c#
.net
reflection
private-methods
Jeromy Irvine
fonte
fonte
BindingFlags.NonPublic
não retornandoprivate
método .. :(BindingFlags.Instance
, bem comoBindingFlags.NonPublic
métodos não estáticos.non-static
eprivate
a classe é herdada deSystem.Web.UI.Page
.. isso me faz de idiota de qualquer maneira .. eu não encontrei o motivo .. :(BindingFlags.FlattenHierarchy
permitirá que você obtenha métodos das classes pai para sua instância.BindingFlags.NonPublic
não retornará nenhum resultado por si só. Como se vê, combiná-lo comBindingFlags.Instance
faz o truque.fonte
internal
funções bemE se você realmente quer ter problemas, facilite a execução escrevendo um método de extensão:
E uso:
fonte
A Microsoft modificou recentemente a API de reflexão, tornando a maioria dessas respostas obsoletas. O seguinte deve funcionar em plataformas modernas (incluindo Xamarin.Forms e UWP):
Ou como um método de extensão:
Nota:
Se o método desejado está em uma superclasse
obj
doT
genérico deve ser explicitamente definido para o tipo de superclasse.Se o método for assíncrono, você pode usar
await (Task) obj.InvokeMethod(…)
.fonte
GetDeclareMethod()
indicar que se destina a ser usado para recuperar apenas um método público.Você tem certeza absoluta de que isso não pode ser feito por herança? A reflexão é a última coisa que você deve considerar ao resolver um problema, pois torna mais difícil a refatoração, a compreensão do seu código e qualquer análise automatizada.
Parece que você deveria ter apenas uma classe DrawItem1, DrawItem2, etc, que substitui seu dynMethod.
fonte
A reflexão especialmente sobre membros privados está errada
A reflexão de membros privados quebra o princípio do encapsulamento e, portanto, expõe seu código ao seguinte:
E se eu devo fazê-lo de qualquer maneira?
Há casos em que, quando você depende de terceiros ou precisa de uma API não exposta, é necessário refletir um pouco. Alguns também o usam para testar algumas classes que possuem, mas não desejam alterar a interface para dar acesso aos membros internos apenas para testes.
Se você fizer, faça certo
Para atenuar o problema fácil de quebrar, o melhor é detectar qualquer possível quebra testando em testes de unidade que seriam executados em uma construção de integração contínua ou algo assim. Obviamente, isso significa que você sempre usa a mesma montagem (que contém os membros privados). Se você usa uma carga e reflexão dinâmicas, gosta de brincar com fogo, mas sempre pode capturar a exceção que a chamada pode produzir.
Nas versões recentes do .Net Framework, o CreateDelegate supera um fator 50 que o MethodInfo chama:
draw
as chamadas serão 50 vezes mais rápidas do que asMethodInfo.Invoke
usadasdraw
como padrãoFunc
:Verifique esta publicação minha para ver referências em diferentes invocações de métodos
fonte
Você não poderia apenas ter um método Draw diferente para cada tipo que deseja desenhar? Em seguida, chame o método Draw sobrecarregado que passa no objeto do tipo itemType a ser desenhado.
Sua pergunta não deixa claro se itemType se refere genuinamente a objetos de tipos diferentes.
fonte
Eu acho que você pode passá-lo
BindingFlags.NonPublic
onde ele é oGetMethod
método.fonte
Invoca qualquer método, apesar de seu nível de proteção na instância do objeto. Aproveitar!
fonte
Leia esta resposta (complementar) (que às vezes é a resposta) para entender para onde está indo e por que algumas pessoas neste tópico reclamam que "ainda não está funcionando"
Eu escrevi exatamente o mesmo código que uma das respostas aqui . Mas eu ainda tinha um problema. Coloquei o ponto de interrupção em
Executou mas
mi == null
E continuou um comportamento como esse até que eu "reconstruí" todos os projetos envolvidos. Eu estava testando uma unidade enquanto o método de reflexão estava na terceira montagem. Era totalmente confuso, mas eu usei o Immediate Window para descobrir métodos e descobri que um método privado que eu tentei fazer no teste de unidade tinha nome antigo (eu o renomei). Isso me disse que a montagem antiga ou PDB ainda está lá, mesmo que o projeto de teste de unidade seja compilado - por alguma razão, o projeto que ele testou não foi construído. "reconstruir" funcionou
fonte
BindingFlags.NonPublic
fonte