Reflection: ParameterModifier problemas com o InvokeMember
Enviado: 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:
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:
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:
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:
Abaixo segue o código completo da solução:
Abraços
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;
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;
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;
Código: Selecionar todos
// atualiza o parametro erro
erro = args[0];
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;