Bunu tam olarak bir ICustomTypeDescriptor arayüzü ve bir Sözlük ile yaptım.
Dinamik özellikler için ICustomTypeDescriptor uygulama:
Son zamanlarda, çalışma zamanında eklenebilen ve kaldırılabilen herhangi bir sayıda özelliğe sahip olabilecek bir kayıt nesnesine ızgara görünümü bağlama gereksinimi duydum. Bu, kullanıcının ek bir veri kümesi girmek için bir sonuç kümesine yeni bir sütun eklemesine izin vermekti.
Bu, her verinin 'satırının' anahtar özellik adı ve değerin bir dize veya belirtilen satır için özelliğin değerini depolayabilen bir sınıf olduğu bir sözlük olarak kullanılmasıyla elde edilebilir. Elbette bir Sözlük nesneleri Listesi'ne sahip olmak bir ızgaraya bağlanamayacaktır. ICustomTypeDescriptor burada devreye girer.
Sözlük için bir sarmalayıcı sınıfı yaratarak ve onu ICustomTypeDescriptor arabirimine bağlı kılarak, bir nesnenin özelliklerini döndürme davranışı geçersiz kılınabilir.
Aşağıdaki veri 'satır' sınıfının uygulanmasına bir göz atın:
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
}
Not: GetProperties yönteminde, PropertyDescriptors'ı performans için okuduktan sonra Önbelleğe Alabilirim, ancak çalışma zamanında sütunları ekleyip kaldırırken her zaman yeniden oluşturulmasını istiyorum
Ayrıca GetProperties yönteminde, sözlük girişleri için eklenen Özellik Tanımlayıcılarının TestResultPropertyDescriptor türünde olduğunu da fark edeceksiniz. Bu, özelliklerin nasıl ayarlandığını ve alındığını yöneten özel bir Özellik Tanımlayıcı sınıfıdır. Aşağıdaki uygulamaya bir göz atın:
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
}
Bu sınıfa bakılacak ana özellikler GetValue ve SetValue'dur. Burada bir sözlük olarak çevrilen bileşeni ve bunun içindeki anahtarın değerinin Ayarlandığını veya alındığını görebilirsiniz. Bu sınıftaki sözlüğün Row wrapper sınıfındaki ile aynı türde olması önemlidir, aksi takdirde çevrim başarısız olur. Tanımlayıcı oluşturulduğunda, anahtar (özellik adı) iletilir ve doğru değeri elde etmek için sözlüğü sorgulamak için kullanılır.
Şu adresteki blogumdan alınmıştır:
Dinamik özellikler için ICustomTypeDescriptor Uygulaması