Adicionar dinamicamente propriedades C # no tempo de execução

Eu sei que há algumas questões que abordam isso, mas as respostas geralmente seguem as linhas de recomendação de um dictionary ou coleção de parâmetros, o que não funciona na minha situação.

Eu estou usando uma biblioteca que funciona através de reflection para fazer muitas coisas inteligentes com objects com propriedades. Isso funciona com classs definidas, bem como classs dinâmicas. Eu preciso dar um passo além e fazer algo ao longo destas linhas:

public static object GetDynamicObject(Dictionary properties) { var myObject = new object(); foreach (var property in properties) { //This next line obviously doesn't work... myObject.AddProperty(property.Key,property.Value); } return myObject; } public void Main() { var properties = new Dictionary(); properties.Add("Property1",aCustomClassInstance); properties.Add("Property2","TestString2"); var myObject = GetDynamicObject(properties); //Then use them like this (or rather the plug in uses them through reflection) var customClass = myObject.Property1; var myString = myObject.Property2; } 

A biblioteca funciona bem com um tipo de variável dinâmica, com propriedades atribuídas manualmente. No entanto, não sei quantas ou quais propriedades serão adicionadas de antemão.

Você já deu uma olhada no ExpandoObject?

veja: http://blogs.msdn.com/b/csharpfaq/archive/2009/10/01/dynamic-in-c-4-0-introducing-the-expandoobject.aspx

Do MSDN:

A class ExpandoObject permite adicionar e excluir membros de suas instâncias em tempo de execução e também definir e obter valores desses membros. Esta class suporta binding dinâmica, que permite usar a syntax padrão como sampleObject.sampleMember em vez de uma syntax mais complexa, como sampleObject.GetAttribute (“sampleMember”).

Permitindo que você faça coisas legais como:

 dynamic dynObject = new ExpandoObject(); dynObject.SomeDynamicProperty = "Hello!"; dynObject.SomeDynamicAction = (msg) => { Console.WriteLine(msg); }; dynObject.SomeDynamicAction(dynObject.SomeDynamicProperty); 

Com base no seu código real, você pode estar mais interessado em:

 public static dynamic GetDynamicObject(Dictionary properties) { return new MyDynObject(properties); } public sealed class MyDynObject : DynamicObject { private readonly Dictionary _properties; public MyDynObject(Dictionary properties) { _properties = properties; } public override IEnumerable GetDynamicMemberNames() { return _properties.Keys; } public override bool TryGetMember(GetMemberBinder binder, out object result) { if (_properties.ContainsKey(binder.Name)) { result = _properties[binder.Name]; return true; } else { result = null; return false; } } public override bool TrySetMember(SetMemberBinder binder, object value) { if (_properties.ContainsKey(binder.Name)) { _properties[binder.Name] = value; return true; } else { return false; } } } 

Dessa forma, você só precisa:

 var dyn = GetDynamicObject(new Dictionary() { {"prop1", 12}, }); Console.WriteLine(dyn.prop1); dyn.prop1 = 150; 

Derivando do DynamicObject permite que você crie sua própria estratégia para lidar com estas solicitações de membros dynamics, cuidado com o fato de haver monstros aqui: o compilador não poderá verificar muitas de suas chamadas dinâmicas e você não obterá intellisense, então continue isso em mente.

Obrigado @Clint pela ótima resposta:

Só queria destacar como foi fácil resolver isso usando o Objeto Expando:

  var dynamicObject = new ExpandoObject() as IDictionary; foreach (var property in properties) { dynamicObject.Add(property.Key,property.Value); }