Durante um projeto encontramos com o seguinte problema:
1 – As camadas da aplicação são divididas em projetos separados para facilitar o versionamento e o reuso em outros projetos e devido ao núcleo (Camadas até a classe de serviços) ser utilizado por várias interfaces (desktop, mobile, web).
2 – Como as camadas geravam class libraries (DLL) , o cliente exigia que as mesmas ficassem em um servidor de Componetes.
3 – O uso deste servidor era primordial, uma vez que o servidor da aplicação não tinha acesso ao servidor de Banco de dados
4 – A aplicação já estava desenvolvida, portanto readaptar o sistema para utilizar tudo baseado em Web Services, não era uma opção
Solução: A melhor solução encontrada foi o uso do Remoting, porém encontramos várias barreiras, pois a nossa camada de persistência utilizava muitos generics.
Conseguimos implementar a solução de Remoting ligando a camada de serviços à camada de interface e posto a seguir um exemplo da solução:
Para isto vamos considerar as seguintes classes no lado do Servidor de Componentes:
Classe de Domínio: Usuário – dentro de uma class library
namespace Dominio
{
public class Usuario
{
private Double dblCodigo;
public Double codigo
{
get { return dblCodigo; }
set { dblCodigo = value; }
}
private String strNome;
public String nome
{
get { return strNome; }
set { strNome = value; }
}
private String strLogin;
public String login
{
get { return strLogin; }
set { strLogin = value; }
}
private String strSenha;
public String senha
{
get { return strSenha; }
set { strSenha = value; }
}
}
}
Classe de Serviço – Class Library
namespace Servico
{
public class UsuarioListagem : MarshalByRefObject, InterfaceRemoting.IUsuarioListagem
{
///
/// Retorna um datatable com uma lista de Usuários
///
public DataTable Listar()
{
Manager manager = new Manager();
IList<Usuario> lstUsuario = null;
//Chamada à persistenca para a listagem de usuários, esta retorna uma lista de usuários (Ilist
lstUsuario = manager.Persistencia.usuario.listar();
DataTable dtUsuario = new DataTable("USUARIO");
dtUsuario.Columns.Add("codigo");
dtUsuario.Columns.Add("nome");
dtUsuario.Columns.Add("login");
dtUsuario.Columns.Add("senha");
foreach (Usuario objUsuario in lstUsuario)
{
DataRow linhaUsuario = dtUsuario.NewRow();
linhaUsuario["codigo"] = objUsuario.codigo.ToString();
linhaUsuario["nome"] = objUsuario.nome.ToString();
linhaUsuario["login"] = objUsuario.login.ToString();
linhaUsuario["senha"] = objUsuario.senha.ToString();
dtUsuario.Rows.Add(linhaUsuario);
}
return dtUsuario;
}
}
}
Servidor Remoting – Console Application (podendo ser um Windows service)
using System.Runtime.Remoting;
using System.Runtime.Remoting.Channels;
using System.Runtime.Remoting.Channels.Tcp;
using System.Runtime.Serialization.Formatters.Binary;
using Servico;
using System.Globalization;
using System.Threading;
namespace Server
{
class Class1
{
//[STAThread]
static void Main(string[] args)
{
try
{
RemotingConfiguration.Configure("Server.config");
RemotingConfiguration.CustomErrorsMode = CustomErrorsModes.Off;
Console.WriteLine("Servidor de Remoting Inciado");
//Esta instrução deve ser repetida para cada classe de Serviço
RemotingConfiguration.RegisterWellKnownServiceType(typeof(UsuarioListagem), typeof(UsuarioListagem).ToString(), WellKnownObjectMode.SingleCall);
foreach (WellKnownServiceTypeEntry teste in RemotingConfiguration.GetRegisteredWellKnownServiceTypes())
{
Console.WriteLine("Servidor inciado: nome - tipo: " + teste.ObjectUri.ToString() + " - " + teste.TypeName.ToString());
}
Console.ReadLine();
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
}
}
}
xml version="1.0" encoding="utf-8" ?>
<configuration>
<system.runtime.remoting>
<application>
<channels>
<channel ref="tcp" port="80">
<clientProviders>
<formatter ref="binary"/>
clientProviders>
channel> />
channels>
application>
system.runtime.remoting>
<system.web>
<globalization culture="pt-BR" uiCulture="pt-BR"/>
system.web>
configuration>
Agora para o lado da interface, deve ser criada uma interface para o serviço:
using System;
using System.Collections.Generic;
using System.Text;
using System.Data;
namespace InterfaceRemoting
{
public interface IUsuarioListagem
{
DataTable Listar();
}
}
Dentro da interface, para “carregar” a interface com o objeto do domínio utilizamos da seguinte forma:
using InterfaceRemoting;
using System.Runtime.Remoting;
using System.Runtime.Remoting.Channels.Tcp;
…
IUsuarioListagem objIUsuarioListagem = (IUsuarioListagem)Activator.GetObject(typeof(IUsuarioListagem), ConfigurationManager.AppSettings["ServicoUsuarioListagem"].ToString());
Assim conseguimos consumir o objIUsuarioListagem.Listar()
OBS: Somente conseguimos utilizar o remoting para métodos do serviço, não conseguimos implemtar para propriedades, pois estas não são automaticamente modificadas na interface quando modificadas dentro do serviço