Esqueceu sua senha? Você pode usar o mecanismo de lembrete neste link: Recuperar senha

Você receberá um link de reativação no email cadastrado.

Não recebeu o email? Lembre-se checar o Lixo Eletrônico.

Reflection: ParameterModifier problemas com o InvokeMember

Discussões gerais sobre a tecnologia .NET
Avatar do usuário
webmaster
Administrador
Mensagens: 2608
Registrado em: Sex Jul 24, 2009 2:44 pm
Contato:

Reflection: ParameterModifier problemas com o InvokeMember

Mensagem por webmaster » Qua Dez 16, 2009 1:22 pm

Vivi isso esses dias. Precisei acessar um componente COM via C#. Nada de muito novo, tinha uma particularidade interessante. O código abaixo mostra o acesso ao componente:

Código: Selecionar todos

Type COM;
object COMObj;
object ReturnObj = null;

object erro = new object();
string Nome = "Fulano";
string Senha = "12354";

// obtém a referência do objeto COM	
COM = Type.GetTypeFromProgID("COM.Autenticao");
// instancia o objeto COM
COMObj = Activator.CreateInstance(COM);
// array de parametros
object[] args = new object[3];
// os parametros
args[0] = erro;
args[1] = Nome;
args[2] = Senha;

// invoca o método
ReturnObj = COM.InvokeMember(
	"Autenticar",
	BindingFlags.DeclaredOnly |
	BindingFlags.Public | BindingFlags.NonPublic |
	BindingFlags.Instance | BindingFlags.InvokeMethod,
	null, 
	COMObj, 
	args); 

return ReturnObj;
Até aí sem problemas. O código funciona perfeitamente, a não ser por um pequeno detalhe. Na função Autenticar, a qual é feito o InvokeMember, o primeiro parâmetro (erro) é um parâmetro por referência. Por esperar-se um valor depois da execução da função, deve-se então explicitamente dizer ao código que o parâmetro é por referência. Isso é feito através do parâmetro ParameterModifier da função InvokeMember, da seguinte forma:

Código: Selecionar todos

Type COM;
object COMObj;
object ReturnObj = null;

object erro = new object();
string Nome = "Fulano";
string Senha = "12354";

// obtém a referência do objeto COM	
COM = Type.GetTypeFromProgID("COM.clsAutenticao");
// instancia o objeto COM
COMObj = Activator.CreateInstance(COM);
// array de parametros
object[] args = new object[3];
// modificador dos parâmetros para passá-los por referência
ParameterModifier modifiers = new ParameterModifier(3);
// os parametros
args[0] = erro;
args[1] = Nome;
args[2] = Senha;

// define os modificadores
modifiers[0] = true;
modifiers[1] = false;
modifiers[2] = false;
// cria o Array de parameter Modifiers (requerido para o InvokeMember)
ParameterModifier[] modifierArray = { modifiers };

// invoca o método
ReturnObj = COM.InvokeMember(
	"Autenticar",
	BindingFlags.DeclaredOnly |
	BindingFlags.Public | BindingFlags.NonPublic |
	BindingFlags.Instance | BindingFlags.InvokeMethod,
	null, 
	COMObj, 
	args, 
	modifierArray, 
	null, 
	null); 

return ReturnObj;
Problema resolvido certo? Quase. Ao executar a função, o seguinte erro é retornado:

System.Reflection.TargetInvocationException, "Object doesn't support this property or method".

Estranhamente, o problema ocorre porque a variável que é passada por referência não pode conter um valor quando pasada para a função. Para resolver o problema, basta mudar a declaração da variável erro para:

Código: Selecionar todos

// de
object erro = new object();
// para
object erro = null;
Com essa mudança, o erro para de acontecer. Resolvemos o problema? Não. Apesar do tipo object ser um tipo por referência, o valor não é reatribuído à variável, mas ao array de parametros informado. Portanto, finalizando o código, bastaria adicionar a seguinte linha antes do final:

Código: Selecionar todos

// atualiza o parametro erro
erro = args[0];
Abaixo segue o código completo da solução:

Código: Selecionar todos

Type COM;
object COMObj;
object ReturnObj = null;

// obtém a referência do objeto COM	
COM = Type.GetTypeFromProgID("COM.clsAutenticao");
// instancia o objeto COM
COMObj = Activator.CreateInstance(COM);
// array de parametros
object[] args = new object[3];
// modificador dos parâmetros para passá-los por referência
ParameterModifier modifiers = new ParameterModifier(3);
// os parametros
args[0] = erro;
args[1] = Nome;
args[2] = Senha;

// define os modificadores
modifiers[0] = true;
modifiers[1] = false;
modifiers[2] = false;
// cria o Array de parameter Modifiers (requerido para o InvokeMember)
ParameterModifier[] modifierArray = { modifiers };

// invoca o método
ReturnObj = COM.InvokeMember(
	"Autenticar",
	BindingFlags.DeclaredOnly |
	BindingFlags.Public | BindingFlags.NonPublic |
	BindingFlags.Instance | BindingFlags.InvokeMethod,
	null, 
	COMObj, 
	args, 
	modifierArray, 
	null, 
	null); 

// atualiza o parametro erro
erro = args[0];

return ReturnObj;
Abraços


Tomás
https://www.tomasvasquez.com.br/blog
https://www.tomasvasquez.com.br/cursocsharp
https://twitter.com/tomamais
Se sua dúvida foi solucionada, acrescente [RESOLVIDO] ao título.

Disable adblock

This site is supported by ads and donations.
If you see this text you are blocking our ads.
Please consider a Donation to support the site.


Responder