Динамически добавлять свойства C# во время выполнения
Я знаю, что есть некоторые вопросы, которые касаются этого, но ответы обычно следуют по линии рекомендации словаря или коллекции параметров, которые не работают в моей ситуации.
Я использую библиотеку, которая работает через отражение, чтобы делать много умных вещей с объектами со свойствами. Это работает с определенными классами, а также динамическими классами. Мне нужно сделать еще один шаг и сделать что-то в этом роде:
public static object GetDynamicObject(Dictionary<string,object> 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<string,object>();
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;
}
в библиотека отлично работает с типом динамической переменной со свойствами, назначенными вручную. Однако я не знаю, сколько или какие свойства будут добавлены заранее.
2 ответов
вы взглянули на ExpandoObject?
из MSDN:
класс ExpandoObject позволяет добавлять и удалять члены его экземпляров во время выполнения, а также устанавливать и получать значения этих членов. Этот класс поддерживает динамическую привязку, которая позволяет использовать стандартный синтаксис, например sampleObject.sampleMember вместо более сложного синтаксиса, такого как sampleObject.GetAttribute ("sampleMember").
позволяет делать классные вещи, как:
dynamic dynObject = new ExpandoObject();
dynObject.SomeDynamicProperty = "Hello!";
dynObject.SomeDynamicAction = (msg) =>
{
Console.WriteLine(msg);
};
dynObject.SomeDynamicAction(dynObject.SomeDynamicProperty);
на основе вашего фактического кода Вы можете быть более заинтересованы в:
public static dynamic GetDynamicObject(Dictionary<string, object> properties)
{
return new MyDynObject(properties);
}
public sealed class MyDynObject : DynamicObject
{
private readonly Dictionary<string, object> _properties;
public MyDynObject(Dictionary<string, object> properties)
{
_properties = properties;
}
public override IEnumerable<string> 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;
}
}
}
таким образом, вам просто нужно:
var dyn = GetDynamicObject(new Dictionary<string, object>()
{
{"prop1", 12},
});
Console.WriteLine(dyn.prop1);
dyn.prop1 = 150;
вывод из DynamicObject позволяет вам придумать свою собственную стратегию для обработки этих динамических запросов членов,будьте осторожны, здесь есть монстры: компилятор Уилл!--23-->не быть в состоянии проверить много динамических вызовов, и вы не получите intellisense, так что просто имейте это в виду.
спасибо @Clint за отличный ответ:
просто хотел подчеркнуть, как легко было решить эту проблему с помощью объекта Expando:
var dynamicObject = new ExpandoObject() as IDictionary<string, Object>;
foreach (var property in properties) {
dynamicObject.Add(property.Key,property.Value);
}