C# .NET: Interagindo com Cursores do Visual FoxPro

Uma prática comum entre os programadores de Visual FoxPro é  utilizar cursores do FoxPro como maneira de retornar múltiplos resultados de uma função, rotina, método, pensando nisso:

Vimos no artigo anterior (Neste artigo) podemos nos comunicar com objetos do FoxPro atráves de uma OleWrapper pelo .NET, com base nisso foi implementado na biblioteca ClicSistemas.Ferramentas uma classe que pode gerenciar os cursores do ambiente do FoxPro pelo .NET

ManagedCursorProvider

O Provedor de Cursor Gerenciável cria uma proxy entre o cursor do FoxPro e o .NET, essa classe está escrita em FoxPro e em .NET, entenda como funciona no diagrama:

ManagedCursorProvider

O funcionamento é bem simples, o ManagedCursorProvider define e implementa várias funções básicas  para trabalhar com o cursor do FoxPro da mesma maneira que o DataReader do .NET. Dentre essas funções inclui:

  • Manipulação do Ponteiro no Cursor
  • Auto-Conversão de Tipos Date e DateTime do FoxPro

Observação:

Esse adaptador é feito somente para leitura de dados, como resultados de rotinas, funções ou métodos em formato de cursores. Caso queria acessar o banco de dados, utilize o OLEDB ou o ODBC.

O Exemplo pode ser baixado aqui:

Exemplo do ManagedCursorProvider

Biblioteca Ferramentas:

Ultimo Release

Documentação 

Plugins para o OleWrapper

C# .NET: Interagindo com o Visual FoxPro atráves de objetos

Uma das grandes barreiras para a maioria das empresas que tem um projeto grande em Visual FoxPro é faze-lo conversar com outras linguagens para reaproveitamento de código. Por isso desenvolvemos uma solução chamada OleWrapper, uma biblioteca em FoxPro que permite que o .NET utilize qualquer objeto do FoxPro ou objetos OLE.


Qual é o problema?

Bibliotecas OLE/COM são DLLs (Dynamic Link Library) registradas no sistema (Windows), essa bibliotecas são fortemente “tipadas” pois o COM Callable Wrapper  precisa saber qual é a definição para que possa replicar a assinatura dos métodos e propriedades dentro do .NET. Isso é um grande problema com o FoxPro pois essa não é uma linguagem fortemente “tipada” fazendo com que seja impossível utilizar objetos entre o FoxPro e o .NET.

Maior descrição do funcionamento disto, pode ser encontrado neste artigo  por  Rick Strahl .

Assim como é explicado no artigo acima, a unica maneira de fazer com que o .NET entenda a assinatura dos objetos do FoxPro pela COM é através de um Hack no MIDL (Compilador IDL), descrito no artigo de Calvin Hsia , que pode ser acessado aqui   com este hack é possível fazer o FoxPro gerar uma DLL com assinaturas fortemente “tipadas” .

Porem isto não resolve o problema , pois para cada objeto e classe que estão armazenados ou sendo utilizados pelos objetos do FoxPro, devem obrigatoriamente implementar uma Interface de Conversão COM, senão, quando o objeto precisar ser transferido do .NET para o FoxPro ou vice e versa, a camada CCW irá falhar pois não encontrara uma conversão válida. Tudo isso resulta em que todo objeto que será usado pelo .NET ou que estará dentro de alguma propriedade dos objetos em FoxPro devem  ser OLEPUBLIC , além de que os métodos que retornam este objeto ou as propriedades deveram estar com  a implementação do Hack (Descrito acima).

Tudo isso acontece, pois o CCW precisa converter toda a assinatura do objeto atual e dos seus parentes quando ele trafegam entre as duas partes. Quando objeto não é reconhecido ele é transferido como IUnknown sendo assim não poderá ser utilizado pelas partes.

Como Funciona?

A OleWrapper evita toda a conversão dos objetos entre as duas partes, ou seja, o objeto que está em FoxPro nunca será convertido para o .NET e vice versa. Mas essa via é de mão unica o que significa que o FoxPro não pode entender os objetos do .NET isso porque seria necessário muita conversão e além de que o Assembly .NET deve estar registrado no sistema e marcado como OLE.

A OleWrapper cria uma proxy entre o objeto em .NET e o objeto na memória do FoxPro fazendo com que ele nunca tenha que ser convertido pela CCW, pois ele sempre se mantem dentro da memória do FoxPro e dentro do contexto dele.

Veja o Diagrama:

OleWrapper

Obs: Para utilizar código .NET em Visual FoxPro veja: wwDotnetBridge


 

Cenário e Recursos Necessários:

O nosso cenário:

Temos uma calculadora escrita em FoxPro que precisamos utilizar dentro do .NET

Solução:

Utilizamos o OleWrapper para criar uma ponte entre o Visual FoxPro e o C# .NET permitindo que ele utilize todas as funcionalidades do Visual FoxPro

Recursos Necessários:

Visual FoxPro 9 Runtime

Visual Studio 2010 ou Superior (O Código for editado no Visual Studo 2015 Community)

Framework da Clic Sistemas para .NET (Download)


 

Implementando a Solução 

Primeiro é necessário registrar a biblioteca OleWrapper que pode ser encontrada nos arquivos da Framework Ferramentas da Clic Sistemas. Ela pode ser registrada pelo RegSvr32 , porém ela se auto-registra quando utilizamos a biblioteca, por isso, é importante rodar o Visual Studio como administrador para que ela se auto-registre. Em um ambiente de produção é importante registrar a DLL com o RegSvr32 em modo administrador ou rodar o código que utiliza a biblioteca como Administrador pelo menos uma vez.

Primeiro, desenvolvemos a classe em FoxPro:

[code language=”vb” gutter=”true” smarttabs=”true” tabsize=”4″ toolbar=”true” padlinenumbers=”true”]

Define Class CalculadoraLib As Custom OlePublic
Function Somar(Numero As Long, Numero2 As Long) As Long
Return (Numero + Numero2)
Endfunc

Function Subtrair(Numero As Long, Numero2 As Long) As Long
Return (Numero – Numero2)
Endfunc

Function Dividir(Numero As Long, Numero2 As Long) As Long
Return (Numero / Numero2)
Endfunc

Function Multiplicar(Numero As Long, Numero2 As Long) As Long
Return (Numero * Numero2)
Endfunc
Enddefine

[/code]

Compilamos o projeto em um biblioteca (DLL), essa biblioteca não vai precisar ser registrada pois ela será encapsulada pelo FoxPro.

Agora nós montamos a interface no .NET:

[code language=”csharp” gutter=”true” smarttabs=”true” toolbar=”true” tabsize=”4″ padlinenumbers=”true”]

public interface ITesteObjeto
{
int Somar(int numero, int numero2);
int Subtrair(int numero, int numero2);
int Dividir(int numero, int numero2);
int Multiplicar(int numero, int numero2);
}

[/code]

Implementamos a Interface em uma classe e utilizamos os atributos do OLEFluent para configurar a classe com a OLE:

[code language=”csharp” gutter=”true” smarttabs=”true” toolbar=”true” tabsize=”4″ padlinenumbers=”true”]
[OLEObjeto("CalculadoraLib", Biblioteca = "CalculadoraLib.dll")]
public class TesteObjeto : ITesteObjeto
{
[OLEMetodo("Dividir")]
public virtual int Dividir(int numero, int numero2)
{
throw new NotImplementedException();
}

[OLEMetodo("Multiplicar")]
public virtual int Multiplicar(int numero, int numero2)
{
throw new NotImplementedException();
}

[OLEMetodo("Somar")]
public virtual int Somar(int numero, int numero2)
{
throw new NotImplementedException();
}

[OLEMetodo("Somar")]
public virtual int Subtrair(int numero, int numero2)
{
throw new NotImplementedException();
}
}
[/code]

É extremamente importante notar que os métodos e as propriedades dever ser definidas como VIRTUAL, pois o OleContexto precisa sobreescrever os métodos desta classe.

Agora nós implementamos o teste:

[code language=”csharp” gutter=”true” smarttabs=”true” tabsize=”4″ padlinenumbers=”true”]
[TestClass]
public class TesteUnitario
{
[TestMethod]
public void Testar()
{
OLEContexto contextoOle = new OLEContexto();
TesteObjeto meuObjeto = contextoOle.CriarInstancia<TesteObjeto>();

// Testa as Operações
Assert.AreEqual(3, meuObjeto.Somar(1, 2));

Assert.AreEqual(4, meuObjeto.Multiplicar(2, 2));

Assert.AreEqual(4, meuObjeto.Dividir(8, 2));

Assert.AreEqual(2, meuObjeto.Subtrair(4, 2));
}
}
[/code]

 

Basta simplesmente rodar o teste.
Download do Código fonte

Observações Importantes

  • O Projeto deve ser compilado para a arquitetura 32 Bits (x86), caso contrário a biblioteca não funcionara já que o FoxPro não suporta compilação x64.
  • Existem problemas com o tipo LONG do C#, por isso, utilizamos o tipo INT nos objetos do .NET
  • A memória é limitada pelo FoxPro pois ele está hospedando os objetos.