none
Instanciar objeto por string RRS feed

  • Pergunta

  • Olá,

    começei a escrever essa pergunta aqui e o fórum me sugeriu alguns links. Olhei todos e ainda não estou conseguindo fazer o que quero.

    Acho que é simples ... preciso instanciar um objecto de uma classe. Só que o nome da classe precisa vir de uma string.

    Exemplo:

    Dim className as String = "UsuarioDAO"
    
    Dim ob = XXX(className)
    


    E preciso que o 'ob' seja uma instancia da classe UsuarioDAO.

    Consegui já chamar funções da mesma classe usando 

    CallByName(Me, "FuncaoASerChamada", CallType.Method)

    mas esse 'Me' precisa ser substituido por outro classe.

    Obrigado.

    terça-feira, 28 de agosto de 2012 15:15

Respostas

  • Uma solução que pegaria bem no seu caso é utilizar o Unity Application Block

    Consiste em:

    Todas as suas classes implementam uma mesma interface

    Ex:

    UsuarioDAO: IEntidadeDAO
    ClienteDAO:IEntidadeDAO

    Você cria uma classe mapper que registra todas as suas entidades

    myUnityContainer.RegisterType<IEntidadeDAO, UsuarioDAO>("Usuario");
    myUnityContainer.RegisterType<IEntidadeDAO, ClienteDAO>("Cliente");

    Finalmente, ao invés de fazer o new das suas instâncias, você deixa que container do Unity faça isso pra você:

    myUnityContainer.Resolve<IEntidadeDAO>("Usuario");// Retorna instância de UsuarioDAO
    myUnityContainer.Resolve<IEntidadeDAO>("Cliente");// Retorna instância de ClienteDAO

    Gosto dessa técnica pois evita o alto acoplamento e dependências entre as classes.

    (Se puder, pesquise mais sobre Injeção de Dependências)

    Ou, um jeito mais simples é fazer os news encadeados dentro do seu switch case mesmo.

    O problema disso é que pode gerar muitos pontos de manutenção caso as classes sofram alguma alteração, (inclusive afetar os pontos onde você faz o new das instâncias)

    Espero ter ajudado

    -----------------------------

    Tiago Saraiva Ferreira


    quinta-feira, 30 de agosto de 2012 04:16

Todas as Respostas

  • Ola Thiago...

    voce pode fazer algo mais ou menos assim:

            Dim assembly = Reflection.Assembly.LoadFile("arquivo.dll")
            Dim instancia = assembly.CreateInstance("namespace.classe")
            Dim metodo = instancia.GetType().GetMethod("metodo")
            Dim parametros As Object() = New Object()
            Dim retorno = metodo.Invoke(instancia, parametros)

    terça-feira, 28 de agosto de 2012 16:43
    Moderador
  • Caso a classe esteje no seu assembly em execução vc pode substituir a primeira linha por:

    Dim assembly = Reflection.Assembly.GetExecutingAssembly()


    Microsoft Community Contributor

    terça-feira, 28 de agosto de 2012 16:46
    Moderador
  • Isso nao te ajuda amigo?

     var teste = Activator.CreateInstance(Type.GetType("System.String"), new object[] { "value".ToCharArray() });


    Se a resposta foi útil por favor qualifique! Janderson Candido de Mattos - MCTS


    terça-feira, 28 de agosto de 2012 17:22
  • Caso a classe esteje no seu assembly em execução vc pode substituir a primeira linha por:

    Dim assembly = Reflection.Assembly.GetExecutingAssembly()


    Microsoft Community Contributor

    Fiz como sugeriu

    Dim assembly = Reflection.Assembly.GetExecutingAssembly()
                Dim instancia = assembly.CreateInstance("UsuarioDAO")
                Dim metodo = instancia.GetType().GetMethod("funcaoTeste")
                Dim parametros As Object() = New Object()
                Dim retorno = metodo.Invoke(instancia, parametros)
    Mas aparece o erro : 

    "Object reference not set to an instance of an object."

    minha "funcaoTeste" nao recebe nenhum parametro.

    terça-feira, 28 de agosto de 2012 18:31
  • Na verdade, o problema mesmo é em instanciar a classe.

    Pois já consigo através do 

    CallByName(instancia, "funcaoTeste", CallType.Method)
    chamar uma função. Só que o primeiro parâmetro desse CallByName, é a instancia da classe (que não consegui fazer)
    terça-feira, 28 de agosto de 2012 18:37
  • Voce ja tentou passar o nome da classe com o Namespace ?

    Dim instancia = assembly.CreateInstance("SeuApplicativo.UsuarioDAO")


    Microsoft Community Contributor

    quarta-feira, 29 de agosto de 2012 13:33
    Moderador
  • Aparece "Object variable or With block variable not set."
    quarta-feira, 29 de agosto de 2012 19:34
  • O problema aí não é código, e sim design.

    Aparentemente você precisa instanciar uma classe, mas o nome da classe é variável, então já tem coisa errada aí.

    quarta-feira, 29 de agosto de 2012 19:47
  • É o único jeito que consegui pensar evitando fazer um select case monstruoso.

    {Tenho uma Grid em um WUC. Uma property do WUC é o nome de uma tabela. Passo por property o nome de qualquer tabela para o WUC e no backEnd do WUC eu instancio uma classe com o mesmo nome da tabela (passado por parametro.). Se não fizer assim, preciso ter um select case pra cada classe que criar na minha aplicação}

    quarta-feira, 29 de agosto de 2012 19:52
  • Property : UsuarioDAO
    'chamar a classe por String

    Dim classeDAO as new "UsuarioDAO" (exemplo)

    Property : ClienteDAO
    'chamar a classe por String

    Dim classeDAO as new "ClienteDAO" (exemplo)

    OU

    Property : UsuarioDAO

    select case
    case "UsuarioDAO"
    ob = new UsuarioDAO
    case "ClienteDAO"
    ob = new ClienteDAO

    quarta-feira, 29 de agosto de 2012 19:56
  • Uma solução que pegaria bem no seu caso é utilizar o Unity Application Block

    Consiste em:

    Todas as suas classes implementam uma mesma interface

    Ex:

    UsuarioDAO: IEntidadeDAO
    ClienteDAO:IEntidadeDAO

    Você cria uma classe mapper que registra todas as suas entidades

    myUnityContainer.RegisterType<IEntidadeDAO, UsuarioDAO>("Usuario");
    myUnityContainer.RegisterType<IEntidadeDAO, ClienteDAO>("Cliente");

    Finalmente, ao invés de fazer o new das suas instâncias, você deixa que container do Unity faça isso pra você:

    myUnityContainer.Resolve<IEntidadeDAO>("Usuario");// Retorna instância de UsuarioDAO
    myUnityContainer.Resolve<IEntidadeDAO>("Cliente");// Retorna instância de ClienteDAO

    Gosto dessa técnica pois evita o alto acoplamento e dependências entre as classes.

    (Se puder, pesquise mais sobre Injeção de Dependências)

    Ou, um jeito mais simples é fazer os news encadeados dentro do seu switch case mesmo.

    O problema disso é que pode gerar muitos pontos de manutenção caso as classes sofram alguma alteração, (inclusive afetar os pontos onde você faz o new das instâncias)

    Espero ter ajudado

    -----------------------------

    Tiago Saraiva Ferreira


    quinta-feira, 30 de agosto de 2012 04:16
  • Esse Unity Application Block tem em VB também ?
    quinta-feira, 30 de agosto de 2012 14:48