Не существует единого способа запроса динамических свойств, обычно ожидается, что вы знаете их заранее. С DynamicObject
разработчики могут переопределить GetMemberNames
, и это обычно дает вам свойства, однако это действительно предназначено для отладки, потому что нет требования, чтобы он предоставлял все свойства. В противном случае, если это ваш DynamicObject
, вам просто нужно написать собственный метод, чтобы получить свойства, основанные на вашей динамической реализации. Например, ExpandoObject
позволяет запрашивать все свойства с помощью интерфейса IDictionary
.
Поэтому, когда у вас есть способ получить ваши свойства, вам нужно сообщить DataGrid. К сожалению, с DataGrid проблема с реализацией ICustomTypeDescriptor
, чтобы сообщить DataGrid о ваших свойствах, заключается в том, что DataGrid получает TypeDescriptors с использованием Type, а не экземпляра, что является проблемой для динамических объектов, однако реализует ITypedList
в коллекции DynamicObjects. будет работать с очень маленькой ошибкой, если вы не реализуете неуниверсальный интерфейс IList
в своей коллекции, он будет удален до того, как будет проверен на ITypeList
.
Итак, в итоге, реализуйте коллекцию с ITypedList
и IList
. С ITypedList
вернуть null для GetListName
и просто реализовать GetItemProperties(PropertyDescriptor[] listAccessors)
; Игнорируйте listAccessors
и возвращайте PropertyDescriptorCollection PropertyDescriptors для каждого члена, названного на основе наиболее представленного экземпляра динамического объекта в вашем списке (скорее всего, только первый объект). Вам необходимо реализовать подкласс PropertyDescriptor, простой и общий способ получения значения Get / Set - это использование инфраструктуры с открытым исходным кодом Dynamitey
using System;
using System.ComponentModel;
using Dynamitey;
public class DynamicPropertyDescriptor:PropertyDescriptor
{
public DynamicPropertyDescriptor(string name) : base(name, null)
{
}
public override bool CanResetValue(object component)
{
return false;
}
public override object GetValue(object component)
{
return Dynamic.InvokeGet(component, Name);
}
public override void ResetValue(object component)
{
}
public override void SetValue(object component, object value)
{
Dynamic.InvokeSet(component, Name, value);
}
public override bool ShouldSerializeValue(object component)
{
return false;
}
public override Type ComponentType
{
get { return typeof(object); }
}
public override bool IsReadOnly
{
get { return false; }
}
public override Type PropertyType
{
get
{
return typeof (object);
}
}
}