Saya telah melakukan persis seperti ini dengan antarmuka ICustomTypeDescriptor dan Kamus.
Menerapkan ICustomTypeDescriptor untuk properti dinamis:
Saya baru-baru ini memiliki persyaratan untuk mengikat tampilan kisi ke objek rekaman yang dapat memiliki sejumlah properti yang dapat ditambahkan dan dihapus saat runtime. Ini untuk memungkinkan pengguna menambahkan kolom baru ke kumpulan hasil untuk memasukkan kumpulan data tambahan.
Hal ini dapat dicapai dengan memiliki setiap 'baris' data sebagai kamus dengan kunci menjadi nama properti dan nilainya menjadi string atau kelas yang dapat menyimpan nilai properti untuk baris yang ditentukan. Tentu saja memiliki objek List of Dictionary tidak akan bisa terikat ke kisi. Di sinilah ICustomTypeDescriptor masuk.
Dengan membuat kelas pembungkus untuk Kamus dan membuatnya sesuai dengan antarmuka ICustomTypeDescriptor, perilaku mengembalikan properti untuk suatu objek dapat diganti.
Lihatlah implementasi kelas 'baris' data di bawah ini:
public class TestResultRowWrapper : Dictionary<string, TestResultValue>, ICustomTypeDescriptor
{
#region Methods
AttributeCollection ICustomTypeDescriptor.GetAttributes()
{
return new AttributeCollection(null);
}
string ICustomTypeDescriptor.GetClassName()
{
return null;
}
string ICustomTypeDescriptor.GetComponentName()
{
return null;
}
TypeConverter ICustomTypeDescriptor.GetConverter()
{
return null;
}
EventDescriptor ICustomTypeDescriptor.GetDefaultEvent()
{
return null;
}
PropertyDescriptor ICustomTypeDescriptor.GetDefaultProperty()
{
return null;
}
object ICustomTypeDescriptor.GetEditor(Type editorBaseType)
{
return null;
}
EventDescriptorCollection ICustomTypeDescriptor.GetEvents(Attribute[] attributes)
{
return new EventDescriptorCollection(null);
}
EventDescriptorCollection ICustomTypeDescriptor.GetEvents()
{
return new EventDescriptorCollection(null);
}
PropertyDescriptorCollection ICustomTypeDescriptor.GetProperties(Attribute[] attributes)
{
List<propertydescriptor> properties = new List<propertydescriptor>();
foreach (string key in this.Keys)
{
properties.Add(new TestResultPropertyDescriptor(key));
}
PropertyDescriptorCollection pdc = TypeDescriptor.GetProperties(this.GetType(), attributes);
foreach (PropertyDescriptor oPropertyDescriptor in pdc)
{
properties.Add(oPropertyDescriptor);
}
return new PropertyDescriptorCollection(properties.ToArray());
}
PropertyDescriptorCollection ICustomTypeDescriptor.GetProperties()
{
return ((ICustomTypeDescriptor)this).GetProperties(null);
}
object ICustomTypeDescriptor.GetPropertyOwner(PropertyDescriptor pd)
{
return this;
}
#endregion Methods
}
Catatan: Dalam metode GetProperties I Could Cache the PropertyDescriptors sekali membaca untuk kinerja tetapi karena saya menambahkan dan menghapus kolom saat runtime, saya selalu ingin mereka dibangun kembali
Anda juga akan melihat dalam metode GetProperties bahwa Deskriptor Properti yang ditambahkan untuk entri kamus memiliki tipe TestResultPropertyDescriptor. Ini adalah kelas Descriptor Properti khusus yang mengatur bagaimana properti disetel dan diambil. Lihat implementasinya di bawah ini:
public class TestResultPropertyDescriptor : PropertyDescriptor
{
#region Properties
public override Type ComponentType
{
get { return typeof(Dictionary<string, TestResultValue>); }
}
public override bool IsReadOnly
{
get { return false; }
}
public override Type PropertyType
{
get { return typeof(string); }
}
#endregion Properties
#region Constructor
public TestResultPropertyDescriptor(string key)
: base(key, null)
{
}
#endregion Constructor
#region Methods
public override bool CanResetValue(object component)
{
return true;
}
public override object GetValue(object component)
{
return ((Dictionary<string, TestResultValue>)component)[base.Name].Value;
}
public override void ResetValue(object component)
{
((Dictionary<string, TestResultValue>)component)[base.Name].Value = string.Empty;
}
public override void SetValue(object component, object value)
{
((Dictionary<string, TestResultValue>)component)[base.Name].Value = value.ToString();
}
public override bool ShouldSerializeValue(object component)
{
return false;
}
#endregion Methods
}
Properti utama untuk melihat kelas ini adalah GetValue dan SetValue. Di sini Anda dapat melihat komponen yang dicor sebagai kamus dan nilai kunci di dalamnya sedang Set atau diambil. Sangat penting bahwa kamus di kelas ini memiliki tipe yang sama di kelas pembungkus baris jika tidak cast akan gagal. Ketika deskriptor dibuat, kunci (nama properti) diteruskan dan digunakan untuk meminta kamus untuk mendapatkan nilai yang benar.
Diambil dari blog saya di:
Implementasi ICustomTypeDescriptor untuk properti dinamis