1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138
|
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace LLVM.ClangTidy
{
/// <summary>
/// The goal of this class is to enable displaying of a PropertyGrid in much the
/// same way that Visual Studio's C++ project system does. A project or file can
/// have properties which might inherit from their parent, or be overridden.
/// It turns out this is somewhat non-trivial. The .NET PropertyGrid is good makes
/// displaying simple properties with a static notion of what constitutes a
/// "default" value very easy. You simply apply an Attribute to the class that says
/// what the default value is and you're done. But when you try to introduce the idea
/// that a property's default value depends on some other factor, things get much more
/// complicated due to the static nature of Attributes.
///
/// The solution to this is to inherit from ICustomTypeDescriptor. This is the mechanism
/// by which you can inject or modify attributes or properties at runtime. The .NET
/// PropertyGrid is designed in such a way that instead of using simple .NET Reflection to
/// look for the properties and attributes on a class, it will invoke the methods of
/// ICustomTypeDescriptor (if your type inherits from it), and ask those methods. Our
/// implementation of ICustomTypeDescriptor works by waiting until the PropertyGrid requests
/// PropertyDescriptors for each of the properties, and then "decorating" them with our
/// own custom PropertyDescriptor implementation which understands the proeprty inheritance
/// model we wish to implement.
/// </summary>
public partial class DynamicPropertyComponent : Component, ICustomTypeDescriptor
{
PropertyDescriptorCollection DynamicProperties_ = new PropertyDescriptorCollection(null);
private DynamicPropertyComponent Parent_;
public DynamicPropertyComponent(DynamicPropertyComponent Parent)
{
Parent_ = Parent;
}
public DynamicPropertyComponent(DynamicPropertyComponent Parent, IContainer container)
{
Parent_ = Parent;
container.Add(this);
InitializeComponent();
}
public AttributeCollection GetAttributes()
{
return TypeDescriptor.GetAttributes(GetType());
}
public string GetClassName()
{
return TypeDescriptor.GetClassName(GetType());
}
public string GetComponentName()
{
return TypeDescriptor.GetComponentName(GetType());
}
public TypeConverter GetConverter()
{
return TypeDescriptor.GetConverter(GetType());
}
public EventDescriptor GetDefaultEvent()
{
return TypeDescriptor.GetDefaultEvent(GetType());
}
public PropertyDescriptor GetDefaultProperty()
{
return TypeDescriptor.GetDefaultProperty(GetType());
}
public object GetEditor(Type editorBaseType)
{
return TypeDescriptor.GetEditor(GetType(), editorBaseType);
}
public EventDescriptorCollection GetEvents()
{
return TypeDescriptor.GetEvents(GetType());
}
public EventDescriptorCollection GetEvents(Attribute[] attributes)
{
return TypeDescriptor.GetEvents(GetType(), attributes);
}
public PropertyDescriptorCollection GetProperties()
{
return DynamicProperties_;
}
public PropertyDescriptorCollection GetProperties(Attribute[] attributes)
{
var Props = DynamicProperties_.OfType<PropertyDescriptor>();
var Filtered = Props.Where(x => x.Attributes.Contains(attributes)).ToArray();
return new PropertyDescriptorCollection(Filtered);
}
public object GetPropertyOwner(PropertyDescriptor pd)
{
return this;
}
public void SetDynamicValue<T>(string Name, T Value)
{
Name = Name.Replace('-', '_');
DynamicPropertyDescriptor<T> Descriptor = (DynamicPropertyDescriptor<T>)DynamicProperties_.Find(Name, false);
Descriptor.SetValue(this, Value);
}
public T GetDynamicValue<T>(string Name)
{
Name = Name.Replace('-', '_');
DynamicPropertyDescriptor<T> Descriptor = (DynamicPropertyDescriptor<T>)DynamicProperties_.Find(Name, false);
return (T)Descriptor.GetValue(this);
}
protected void AddDynamicProperty<T>(string Name, Attribute[] Attributes)
{
Name = Name.Replace('-', '_');
// If we have a parent, find the corresponding PropertyDescriptor with the same
// name from the parent.
DynamicPropertyDescriptor<T> ParentDescriptor = null;
if (Parent_ != null)
ParentDescriptor = (DynamicPropertyDescriptor<T>)Parent_.GetProperties().Find(Name, false);
DynamicProperties_.Add(new DynamicPropertyDescriptor<T>(Name, ParentDescriptor, Name, Attributes));
}
}
}
|