Method that returns a class

Asked

Viewed 5,290 times

6

I am trying to create a method that takes a string and returns an instance of the class with the name passed, example: "Calculator", will return me an instance of the class "Calculator" (If it exists), I have a problem at the time of setting which type it returns, 'Cause from what I’ve researched, I need to get the guy to the method, too. I tried to: Type Tipo = Type.GetType("NomeDaClasse"); and then passing var x = RetornaClasse<Tipo>("Calculadora"); but without success. (I can’t even set the method to try to use.

static T RetornaClasse<T>(string nome) where T : class
{
    return (T)Assembly.GetExecutingAssembly().CreateInstance(nome);
}

Use: the return of this method will be parameter for this Generic Class:

public class Generico<T> where T : class
{
    public T Objeto { get; set; }

    public string ListarAtributos()
    {
        var p = Objeto.GetType().GetProperties();
        string atributos = String.Empty;

        foreach (PropertyInfo pop in p) // Lista de atributos
            atributos += (String.Concat("[", pop.Name, "] = [", pop.GetValue(Objeto, null), "]\n"));

        return atributos;
    }

    public string[] ListarMetodos()
    {
        var m = Objeto.GetType().GetMethods();
        string[] metodos = new string[m.Length];

        for (int i = 0; i < m.Length; i++)
            metodos[i] = String.Concat(i, " [+] ", m[i].Name, "\n");
        return metodos;
    }

    // TODO: Setar atributos, usar métodos
}

Solution:

static object RetornaClasse(string nome)
{
    var classe = Assembly.GetExecutingAssembly().GetTypes().First(x => x.Name == nome);
    var instancia = Activator.CreateInstance(classe);
    return instancia;
}
  • The guy’s in the same Assembly, or a third party?

  • In the same Assembly.

  • You would be able to edit the question, indicating how you intend to use the return method?

  • If the methods and properties will be accessed via reflection, then there is no need for the generic parameter.

  • I think the confusion is on that line T RetornaClasse<T>(string nome) where T : class ... this does not return a class by itself, but rather an instance of a T object, in which T can only be a class and not a struct. That is, when calling the method RetornaClasse only classes can be specified as generic parameter, and not structs: RetornaClasse<string>() is valid because string is class, RetornaClasse<int> is not valid because int is struct.

  • I took your advice and took the <T> parameter from the Generic class and changed the attribute to Object, I left the method returning an Object, only now it instantiates but I can’t use the empty constructor of the "Calculator" class, as I prompt it with the empty constructor (I came to reset the parameters), EDIT: I managed!

  • 1

    It’s using the method Activator.CreateInstance(tipo).

  • That’s what I did! Thank you Miguel! :)

  • I edited the answer with an example of how to use an object using reflection, and using dynamic... I think it will be in your interest to check the use of Dynamic in this case, as it makes it much easier.

Show 4 more comments

1 answer

8


If the type is in the same Assembly that is running, you can do so:

var t = Assembly.GetExecutingAssembly().GetTypes().First(x => x.Name == "Calculadora");

And then use the type to create a new instance:

var objectOfType = Activator.CreateInstance(t);

Example of a fully functional program, using generic argument, and LINQ to make it a little easier:

public class Program
{
    public static void Main(string[] args)
    {
        var computador = GetInstanciaDoTipo<Computador>("Calculadora");

        var usarReflexao = new UsandoReflexaoParaAcessarObjeto();
        usarReflexao.Objeto = computador;
        var resultado1 = usarReflexao.TentarSomar();
        var resultado2 = usarReflexao.SomarUsandoDynamic();
        var resultado3 = computador.Somar(1, 2);
    }

    private static T GetInstanciaDoTipo<T>(string nomeTipo)
    {
        return
            (T)Assembly.GetExecutingAssembly()
                .GetTypes()
                .Where(t => t.Name == nomeTipo)
                .Where(t => typeof(T).IsAssignableFrom(t))
                .Select(Activator.CreateInstance)
                .First();
    }

    abstract class Computador
    {
        public abstract int Somar(int a, int b);
    }

    class Calculadora : Computador
    {
        public override int Somar(int a, int b)
        {
            return a + b;
        }
    }

    /// <summary>
    /// Esta classe usa reflexão para acessar o objeto, seja lá qual o tipo dele.
    /// Também há um método usando dynamic, para exemplificar como é mais fácil usar dynamic do que reflection,
    /// quando queremos executar algo dinamicamente.
    /// </summary>
    public class UsandoReflexaoParaAcessarObjeto
    {
        public object Objeto { get; set; }

        public int? TentarSomar()
        {
            if (this.Objeto != null)
            {
                var type = this.Objeto.GetType();
                var methodInfo = type.GetMethod("Somar");
                var result = methodInfo.Invoke(this.Objeto, new object[] { 1, 2 });
                return (int)result;
            }

            return null;
        }

        public int? SomarUsandoDynamic()
        {
            if (this.Objeto != null)
            {
                dynamic dyn = this.Objeto;
                return dyn.Somar(1, 2);
            }

            return null;
        }
    }
}
  • And how would that look in the method? I ask because I’m trying to do it because I have a generic class that receives a class and this method would serve as a parameter of the same, this way you did using var, C# does not let me pass as parameter to class (He does not know that var will be a class type). public class Generico<T> where T : class

  • I made a method GetInstanciaDoTipo that allows you to pass as a generic parameter a T from which the class being searched inherits or implements... is that it? I don’t quite understand yet in what context you want to use the return of this method.

  • I posted the Generic class I spoke about, my goal Miguel is to study Reflection, in this Generic class I will create methods that will use the methods of the past classes, set attributes, I want to give the user the freedom to choose the class he wants to interact with, so I’m trying to take her name and then instantiate her to use in the Generic class.

Browser other questions tagged

You are not signed in. Login or sign up in order to post.