Esse é o terceiro post sobre como rodar Ruby no .Net, com IronRuby, e integrado ao C#. Estou usando o Visual Studio 2010 que é onde as coisas funcionam mais bem integradas, mas o primeiro post dá pra trabalhar ainda com o Visual Studio 2008. Os posts anteriores estão aqui:
- Rodando Ruby com C#: Parte 1
- Rodando Ruby com C#: Parte 2 – chamando uma classe Ruby no C#
No primeiro post eu mostrei como configurar o ambiente, e no post seguinte executamos código Ruby via .Net, inclusive passando parâmetros, e pegamos o retorno e utilizamos no C#. Utilizamos classes Ruby no C# normalmente com as novas capacidades dinâmicas do C# 4.
Neste post vou mostrar como fazer o contrário: tenho uma classe no C# que quero ser capaz de chamar a partir do Ruby. Isso é possível, vamos ver como.
Primeiro vou definir a classe que quero chamar do C#. Segue o mesmo molde das classes de antes, ela tem só um método que recebe dois parâmetros, e retorna uma string de acordo com os argumentos recebidos:
public class Teste
{
public string Chamar(bool flag, string texto)
{
return flag ?
texto + "sufixo" :
texto;
}
}
Quero chamar o método “Chamar” desta classe a partir do Ruby. Para poder fazer isso, preciso dizer pra ele referenciar minha dll de alguma forma. No Ruby, a maneira que você usa pra ele acessar outros arquivos Ruby é com a palavra chave “require”. Se você escrever “require MeuArquivo” o Ruby vai tentar encontrar o arquivo “MeuArquivo.rb” nos diretórios especificados na variável $LOAD_PATH, que normalmente inclui o diretório local (.). Pra saber quais são esses diretórios basta inspecionar a variável:
No IronRuby, além de procurar arquivos .rb, o require vai procurar também dlls. Então você precisa acrescentar uma linha de require com o nome da sua DLL.
O código Ruby então fica assim:
require 'IronRubyNetFX4Test1'
IronRubyNetFX4Test1::Teste.new
Na primeira linha eu referencio meu assembly de testes, que é chamado IronRubyNetFX4Test1.dll. Na linha seguinte eu crio a classe Teste que havia especificado. Notem que os dois pontos duplos :: separaram a especificação do namespace e da classe. Como no Ruby a última linha sempre retorna o resultado, a classe Teste do C# está sendo retornada. O objeto retornado é entendido pelo C# como um objeto dinâmico, e pode ser chamado. Vejam o teste todo:
[TestMethod]
public void ConsigoCriarUmObjetoDotNetEChamarUmMetodoDinamicamenteUsandoONomeCompletoDoTipoEVariavelDinamica()
{
var source = @"
require 'IronRubyNetFX4Test1'
IronRubyNetFX4Test1::Teste.new";
var scriptSource = _defaultScriptEngine.CreateScriptSourceFromString(source);
var teste = scriptSource.Execute();
var resultado = teste.Chamar(true, "ttt");
Assert.AreEqual("tttsufixo", resultado);
}
Mas eu poderia fazer um cast do retorno, já que o tipo retornado é um tipo .Net, e usá-lo normalmente:
[TestMethod]
public void ConsigoCriarUmObjetoDotNetEChamarUmMetodoDinamicamenteUsandoONomeCompletoDoTipoEVariavelEstatica()
{
var source = @"
require 'IronRubyNetFX4Test1'
IronRubyNetFX4Test1::Teste.new";
var scriptSource = _defaultScriptEngine.CreateScriptSourceFromString(source);
var teste = (Teste)scriptSource.Execute();
var resultado = teste.Chamar(true, "ttt");
Assert.AreEqual("tttsufixo", resultado);
}
Faz mais sentido, se eu sei que o retorno é um tipo conhecido do C#.
O Ruby tem ainda uma palavra chave que faz a importação do namespace, semelhante ao “using” do C#, é o “include”. E nós podemos usá-la também:
[TestMethod]
public void ConsigoCriarUmObjetoDotNetEChamarUmMetodoDinamicamenteUsandoOInclude()
{
var source = @"
require 'IronRubyNetFX4Test1'
include IronRubyNetFX4Test1
Teste.new";
var scriptSource = _defaultScriptEngine.CreateScriptSourceFromString(source);
var teste = scriptSource.Execute();
var resultado = teste.Chamar(true, "ttt");
Assert.AreEqual("tttsufixo", resultado);
}
Com isso, fecho os exemplos do Ruby chamando o C#. Já conseguimos fazer código Ruby chamar C#, e vice-versa. A seguir vou mostrar alguns cenários onde penso que isso pode ser útil. Em breve.
f174eba9-5033-44d5-833d-db8fde04469b|0|.0