Denis Bittencourt Muniz Postado Outubro 30, 2005 Denunciar Share Postado Outubro 30, 2005 Tenho esse código:<% @ Page Language = "C#" %> <% Response.Expires = 0; %> <% object objConn, objRS; %> <% objConn = Server.CreateObject("ADODB.Connection"); objConn.Open("DSN=Funcionarios;Database=Funcionarios;UID=;PWD=;"); objRS = Server.CreateObject("ADODB.Recordset"); objRS.ActiveConnection = objConn; objRS.Open("SELECT * FROM Funcionarios"); while(! objRS.EOF){ Response.Write(objRS("Nome")+"<br>"); objRS.MoveNext; } objRS.Close; objConn.Close; objRS = null; objConn = null; %> E dá esse erro:CS0117: 'object' does not contain a definition for 'Open'Nessa linha:objConn.Open("DSN=Funcionarios;Database=Funcionarios;UID=;PWD=;");Mas no caso, qual seria o tipo de variável que eu usaria, pois entendi o que o tipo object não é o tipo correto.. Qual seria? Alguma solução?Falows! Citar Link para o comentário Compartilhar em outros sites More sharing options...
0 Graymalkin Postado Outubro 30, 2005 Denunciar Share Postado Outubro 30, 2005 C# é fortemente tipada e não tem o recurso de late-binding existente no VB. Ou seja, *nós* sabemos que estes métodos e propriedades existem no objeto quando o mesmo é criado. Porém, o compilador não sabe e nem vai saber até que o objeto seja de fato criado, o que só ocorre durante a execução. Por isso que esse código acima não funciona no C# (mas funciona no VB).Aliás, uma vez fiz um artigo exatamente sobre isso. Não me lembro onde que ele está na web, mas segue a cópia do mesmo que tenho aqui:Utilizando a técnica de Late-Binding em C#A tecnologia COM/ActiveX será um legado que perdurará por muito tempo, e pode ser que a substituição de um sistema antigo por um novo implique na reutilização de componentes deste tipo. Pensando nisso, a Microsoft fez com que a .NET Framework fosse 100% compatível com esta tecnologia (para nossa felicidade!). Porém, é comum a utilização de componentes COM através de late-binding, ou seja, através de um processo em que o componente, seus métodos, propriedades, etc. são resolvidos em tempo de execução. A vantagem disso é a fácil substituição do componente, sem efeitos colaterais. O uso de late-binding em VB.NET é super-amigável, já que é uma característica própria da linguagem (já estava presente desde versões passadas da linguagem, na era pré-.NET). Nesta, a utilização de um objeto COM não difere de qualquer outro objeto criado nativamente. Em C# já não se tem essa facilidade, e esse foi o principal motivo para que este artigo fosse realizado: em C# precisa-se utilizar Reflection para manipulação de componentes COM através de late-binding.Em VB.NET emprega-se a técnica de duck-typing[1] (do inglês, "tipagem pato") quando se utiliza o tipo Object, que vem de um conceito simples porém muito interessante: "se anda e grasna como um pato, então é um pato!". Ou seja, não importa qual o tipo do objeto, desde que ele ofereça a interface que esperamos (métodos, propriedades, eventos, etc.). Daí, conclui-se que tanto faz se o objeto é um "pato" ou um "marreco", desde que os métodos valham para ambos. Por essa razão é que o código abaixo é válido: Module Exemplo Sub Main() Dim winword As Object = CreateObject("Word.Application") winword.Documents.Add() winword.Selection.TypeText("teste") winword.Visible = True End Sub End Module É de conhecimento geral que todos os aplicativos da suite Microsoft Office podem ser automatizados através de objetos COM, e no exemplo acima o Microsoft Word é utilizado nesse sentido. Como o foco do artigo não é a automação do Microsoft Office, e sim a utilização de objetos COM em geral, o exemplo é simplório e visa apenas demonstrar a resolução em tempo de execução de métodos, objetos e propriedades. O objeto "winword", por ser do tipo Object, só possui, de verdade, um único método chamado GetType(). No entanto, o compilador não reclama de fazermos referência a objetos, métodos e propriedades contidos nele. *Nós* sabemos que eles existirão quando o programa estiver sendo executado, por isso deixamos com que sejam resolvidos durante a execução. Vale ressaltar que a diretiva Option Strict deve estar como Off, que já é o padrão, para que isso seja permitido. Caso Option Strict esteja ligada (On), o comportamento do VB.NET será o mesmo de C#, ou seja, ele resolverá os métodos e atributos em tempo de compilação. Em contrapartida, C# é fortemente tipada, o que significa que não adianta você entregar um "marreco" no lugar de um "pato"; o compilador vai reclamar. É claro que existem formas de remediar isso através de herança (através do polimorfismo dinâmico, é possível passar um objeto filho para um objeto do tipo pai), interfaces e classes abstratas. Através destas últimas duas, qualquer classe que herde/implemente-as, obrigatoriamente, obedecerá ao esquema definido na interface/classe. Para isso, criar-se-ia uma classe, interface ou classe abstrata chamada Anatídeo (nome da família dos patos e marrecos) e herdar/implementar-se-ia ela nas classes Pato e Marreco. É claro que essas são soluções mais sensatas quando se está criando classes que são substituíveis por outras compatíveis. Todavia, o nosso caso aqui é utilizar componentes já prontos, cujas interfaces não são a preocupação maior. A mistura feita aqui entre COM/duck typing/interfaces/late-binding é proposital: duck typing é um meio interessante de se utilizar componentes COM através de late-binding sem a utilização "direta" de interfaces. Sua aplicação não fica "presa" a determinado componente (de uma certa forma). Alguns questionam essa maneira de se programar, mas não acredito que ela possa ser condenável. Em todo caso, esse não é o foco do artigo por isso não enveredaremos por esse caminho. Vejamos agora como ficaria em C# aquele mesmo exemplo ali de cima, que abre o Word, escreve "teste" e o torna visível: using System; using System.Reflection; class Exemplo { static void Main(string[] args) { Type tipoWord = Type.GetTypeFromProgID("Word.Application"); Type tipoDocuments, tipoSelection; object winword = Activator.CreateInstance(tipoWord); object Documents, Selection; Documents = tipoWord.InvokeMember("Documents", BindingFlags.GetProperty, null, winword, new Object[] {}); tipoDocuments = Documents.GetType(); tipoDocuments.InvokeMember("Add", BindingFlags.InvokeMethod, null, Documents, new Object[] {}); Selection = tipoWord.InvokeMember("Selection", BindingFlags.GetProperty, null, winword, new Object[] {}); tipoSelection = Selection.GetType(); tipoSelection.InvokeMember("TypeText", BindingFlags.InvokeMethod, null, Selection, new Object[] {"teste"}); tipoWord.InvokeMember("Visible", BindingFlags.SetProperty, null, winword, new object[] {true}); } } A primeira coisa que temos que notar é que, como não temos o objeto em si para manipular seus métodos e propriedades, precisamos utilizar seu tipo (Type) para fazer as chamadas. No caso, tipoWord é o tipo de Word.Application, tipoDocuments é o tipo de Word.Application.Documents e o tipoSelection é o tipo de Word.Application.Selection. Usando o método CreateInstance() da classe Activator, podemos então criar um objeto da classe (tipo) tipoWord, que ficará referenciado pelo objeto winword. O tipo de winword é Object, o tipo pai-de-todos, ou seja, aquele que pode armazenar uma referência para qualquer objeto de qualquer classe. Todavia, como já foi dito antes, apesar de sabermos que esse objeto terá outros métodos e propriedades, além das já existentes em qualquer Object, o compilador não nos deixará usá-los. Isso porque eles não estão realmente lá, só surgindo em tempo de execução. Dessa maneira, para fazermos... winword.Documents.Add() ... temos que primeiro obter o objeto Documents que está contido em winword. E, do mesmo modo, teremos que obter o tipo (Type) de Documents para poder manipulá-lo (tipoDocuments), o que é feito através do método GetType() do objeto. Só então é que poderemos chamar o método Add() do mesmo. E segue-se o mesmo procedimento para obter Selection e chamar seu método TypeText().O ponto vital aqui é o método InvokeMember() que capaz, como o nome sugere, invocar um membro do referido objeto. Por membro, podemos destacar métodos, propriedades e campos públicos. Vamos nos estender um pouco mais sobre este método agora.Vou me atear à assinatura de InvokeMember utilizada aqui: public object InvokeMember(string name, BindingFlags invokeAttr, Binder binder, object target, object[] args);O primeiro parâmetro de InvokeMember (name) é o nome do membro a ser "invocado", passado em uma string. O segundo parâmetro (invokeAttr) é como vamos invocar o desejado membro. Algumas possibilidades para isso são:InvokeMethod - para chamar um métodoGetProperty - para obter o valor de uma propriedadeSetProperty - para definir o valor de uma propriedadeBasicamente vou me ater a estes, já que são os utilizados aqui. Estas constantes e as demais podem ser encontradas na classe BindingFlags (dentro de System.Reflection).O próximo parâmetro (binder) é um objeto Binder, que serve para fazer conversões de tipos ao invocar o membro; como uma camada para fazer ajustes nos parâmetros. No nosso caso isso não é importante, por isso pode-se passar simplesmente null (Nothing no VB.NET) para que seja utilizado o binder padrão.O parâmetro seguinte (target) é o próprio objeto em questão, o alvo. Uma vez que estamos pedindo ao tipo para invocar o membro do objeto, temos que informar qual o objeto. Ou seja, podemos ter apenas uma referência ao tipo (tipoWord) e ter vários objetos dele (winword1, winword2, winword3, etc.), utilizando o mesmo tipo para manipular todos os objetos (já que estes são explicitamente passados).O último parâmetro (args) é um array de object no qual informaremos os parâmetros a serem passados para o método/propriedade/campo, etc. Ao chamar o método TypeText, no exemplo acima, temos um array de object com uma string (com o texto "teste"), porque este é o único parâmetro a ser passado para o método. Outro exemplo é para tornarmos o Word visível, o que é feito pela propriedade Visible, no qual criamos um array de object apenas com true. Se fossem dois, três, quatro, n-parâmetros, todos eles deveriam ser informados nesse array (e como é um array de Object, todos os outros tipos podem ser comportados).[1] http://en.wikipedia.org/wiki/Duck_typingMas, acredito que o melhor para o seu caso seria a utilização do ADO.NET que é o método nativo da .NET Framework para acesso a dados. Dê uma procurada aqui no fórum e você encontrará exemplos.Abraços,Graymalkin Citar Link para o comentário Compartilhar em outros sites More sharing options...
Pergunta
Denis Bittencourt Muniz
Tenho esse código:
E dá esse erro:
Nessa linha:
Mas no caso, qual seria o tipo de variável que eu usaria, pois entendi o que o tipo object não é o tipo correto.. Qual seria? Alguma solução?
Falows!
Link para o comentário
Compartilhar em outros sites
1 resposta a esta questão
Posts Recomendados
Participe da discussão
Você pode postar agora e se registrar depois. Se você já tem uma conta, acesse agora para postar com sua conta.