Is there a way to dynamically add attribute to instantiated object in C#?

Asked

Viewed 258 times

2

Well, in C# we put attributes as follows:

[Required("Este campo é obrigatório")]
public string Nome {get; set;}

What I would like to know is whether there is a way to add attributes dynamically to instantiated objects. Like the following hypothetical code:

var pessoa = new Pessoa();
pessoa.Nome.AdicionarAtributo(Required());

Context

The context is as follows: I am creating a Universal Windows project, using Prism and applying MVVM. But for each field of a model I am creating a field in Viewmodel, then in the Save() method, I create an instance of the model and assign the values of Viewmodel. The attributes, at the moment, are in the fields of Viewmodel, but I wanted to do something different. My Viewmodel would be basically this way:

public class ClienteViewModel: ValidatableBindableBase
{
    private Cliente _modelo;

    public Cliente Modelo
    {
        get => _modelo;
        set => SetProperty(ref _modelo, value);
    }
    public ClienteViewModel()
    {
        Modelo.Campo.AdicionarAtributo(Required());
        [...]
    }

    [...]
    public void Salvar()
    {
        if(ValidateProperties()){
            _serviço.Salvar(_modelo);
        }
    }
}    

My goal is to decontaminate my Viewmodel, if anyone knows an even better way to do this, it will be very welcome.

3 answers

2


The instantiated object cannot, attributes exist in types and their members, not in instances. It’s usually what you need, and you almost always have no reason to put it dynamically, it takes more work, you have a better chance of something going wrong without a real gain.

It doesn’t really make sense what you want. And if you do it for yourself you should use a dynamic language and not C#. I think it’s polluting a guy, not the opposite.

If you think you’re doing a lot of manual labor, I welcome you to the world of complex architectures. Either start making simpler architectures or live with it.

Perhaps, a better solution would be to create a code generator. In some cases it is well suited.

  • Manual labor would not even be so much the problem, actually I worry more the code getting ugly and polluted haha. I did some research and saw something about putting an object between the model and Viewmodel, and in this object the properties and attributes I want, basically letting viewmodel take care only of the commands... do you think this is valid? Or is it just more work for little return?

  • 1

    I would need to see in detail, but Viewmodel should be super simple, only with the properties

1

I haven’t tried it yet, I’ve seen people say it’s not possible, but some saying it’s possible :)

There is the

TypeDescriptor.AddAttributes(Object, Attribute[])

There is also this example with the Fastdeepcloner

public class test{
public string Name{ get; set; }
}

var prop = now DeepCloner.GetFastDeepClonerProperties(typeof(test)).First();
prop.Attributes.Add(new JsonIgnoreAttribute());
// now test and se if exist 
prop = now DeepCloner.GetFastDeepClonerProperties(typeof(test)).First();
bool containAttr = prop.ContainAttribute<JsonIgnoreAttribute>()
// or 
JsonIgnoreAttribute myAttr = prop.GetCustomAttribute<JsonIgnoreAttribute>();

Source: https://stackoverflow.com/a/46256356/194717

1

To clean up Viewmodel, I’ll tip off Nuget Propertychanged

public class ClienteViewModel: ValidatableBindableBase, INotifyPropertyChanged
{
    public event PropertyChangedEventHandler PropertyChanged;

    public Cliente Modelo {get; set;}

    public ClienteViewModel()
    {
        Modelo.Campo.AdicionarAtributo(Required());
        [...]
    }

    [...]
    public void Salvar()
    {
        if(ValidateProperties()){
            _serviço.Salvar(Modelo);
        }
    }
}    
  • Thanks Tony, but Prism already implements this interface in the Setproperty() method; The other solution is how to put chains on the wheels, would end up giving me more work, but it was worth showing me that this is possible.

Browser other questions tagged

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