Access object attribute passed as generic parameter

Asked

Viewed 923 times

1

In my application I have a chained list class that takes a generic parameter, which is the type of value the list will store. In this case, I am passing as parameter the class Usuario, I need to check if there is already a Usuario registered with the informed CPF. For this, I created the method Procura, to which I inform the value I wish to compare and the attribute I need to access, but the following error is occurring:

System.Nullreferenceexception: 'Object reference not set to an instance of an object.'

System.Type.Getproperty(...) returned null.

Apparently, GetProperty() is returning null. How can I solve this problem?

public class ListaEncadeada<T>{

    ...

    public Boolean Procura(String valor, String atributo)
    {
        var atual = cabeca;
        while (atual != null)
        {
            var obj = atual.Valor;
            String aux = obj.GetType().GetProperty(atributo).GetValue(obj).ToString();
            if (aux == valor)
            {
                return true;
            }
            atual = atual.Proximo;
        }
        return false;
    }
}

.

private void Form1_Load(object sender, EventArgs e)
{
    ...
    //verificar se já existe um usuário com o cpf informado.
    listaUsuario.Procura(valor, "cpf");
}

.

public class Usuario
{
    private String nome;
    private String cpf;
    private String senha;

    ...
 }
  • The estate cpf exists under the same name (attention to case sensitive) in the object obj?

  • @Joãomartins, exists in the User class, to which the object belongs.

  • Do debug and check whether the object obj is correctly filled, of what type is and if you have the properties you want.

  • @Joãomartins, yes, I did the debug and the object is correctly filled, but using the Getproperties() method nothing is returned.

2 answers

3


First let’s agree to use the correct terms. You’re calling an attribute what is actually called a field. And that may be why you used the wrong reflection method. If you want to take a field, use the GetField() and not the GetProperty(), a field is different from a property.

Nor do I think you should change the field to a property just to use the method, each has a reason to use. I won’t question what’s right for you in this scenario, because it has no details of this scenario, I will only trust that you needed fields and that’s why you used them, and now you just need to use the right reflection to get what you need.

I just put public down so I can initialize easily since there is no builder (should).

using static System.Console;

public class Program {
    public static void Main() {
        var obj = new Usuario();
        obj.nome = "João";
        WriteLine(obj.GetType().GetField("nome").GetValue(obj).ToString());
    }
}

public class Usuario {
    public string nome;
    public string cpf;
    public string senha;
}

Behold working in the ideone. And in the .NET Fiddle. Also put on the Github for future reference.

Another important detail: the chance of something going wrong there is great if the program makes a mistake. I will not try to treat because I do not know your need, I can do something that solves the error but gives unexpected results, can end up swallowing the error silently and be worse still, only you know what is appropriate.

Use of reflection in C# is almost always wrong, transforms the language into dynamic and takes all the disadvantages of this type of language. You are giving up the advantages of C#. You almost always have better solutions. The reflection is almost always to save the programmer’s typing, which is a silly economy. It loses robustness and loses performance. At the very least, this should be handled better if a non-existent field name comes along, which would increase code complexity and further decrease performance. Or you can make an external tool to analyze the code statically, but then it’s easier to create a code generator that gives the same result without using reflection.

0

Your problem is how you declared the properties in the class Usuario (or, in this case, did not declare! ), in addition to which put them all as Private, being impossible something "outside" to access them.

If you don’t put a getter and/or a Setter, { get; set; }, your variables will not go beyond that, variables. So that they are effectively estates, needs to have that definition.

In this scenario the solution is to change the class Usuario to the following:

public class Usuario
{
    public string nome { get; set; }
    public string cpf { get; set; }
    public string senha { get; set; }
}

When trying to obtain the value of the property, you should always take into account the fact that one of the Get be able to return null, so it is recommended that this validation, which can be done as follows (using the conditional null and the conversion to string):

string aux = Convert.ToString(usuario.GetType().GetProperty("cpf")?.GetValue(usuario));

Thus the variable aux or gets the amount you want or with empty string ("").

Browser other questions tagged

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