Understanding TypeDescriptor/PropertyDescriptor/etc
See the code:
class DataItem
{
public DataItem(int num, string s)
{
Number = num;
Str = s;
}
public int Number { get; set; }
public string Str { get; set; }
}
static void Main(string[] args)
{
var data = new DataItem(2, "hi");
var provider = TypeDescriptor.AddAttributes(typeof(DataItem),
new SerializableAttribute());
var another = provider.CreateInstance(null, typeof(DataItem),
new Type[] { typeof(int), typeof(string) },
new object[] { 100, "hello" }) as DataItem;
var newProperty = TypeDescriptor.CreateProperty(another.GetType(), "Str",
typeof(string),
new DescriptionAttribute("new property"));
//newProperty.SetValue(another, "new one");
Console.WriteLine(newProperty.GetValue(another));
开发者_StackOverflow Console.Read();
}
And I have several questions for the code:
(1) I added a SerializableAttribute
to the Type of DataItem, what is this "change" applied to? I can't get this attribute by typeof(DataItem).GetCustomAttributes(true)
.It seems that the change is not applied to the "essential DataItem", it is stored in the TypeDescriptionProvider temporarily?
(2) The instance another
is created by the provider(where we added the attribute), I think now this variable is the same as the one created by the constructor of SerializableAttributed DataItem? even if we can't still get the attribute by another.GetType().GetCustomAttributes
.
(3) Another reason I believe the change is temporarily stored in the provider is that I tried to create a property with its name Str
and type string
, which actually already exists in DataItem
. The code will output hello
. And if I uncomment the SetValue
method, the output will be new one
. Do I have any misunderstandings?
The attributes are added to the instance (data) not the type. Have you tried TypeDescriptor.AddAttributes(typeof(DataItem)) instead?
TypeDescriptor
, being in System.ComponentModel
, is a part of a large but isolated ecosystem of components and related technologies. The purpose of this class is to manipulate design-time (unlike reflection which is compile-time, or run-time DLR) members of a type or instance. This is the case when you create or edit a component in the Visual Studio designer, or in controls like PropertyGrid
, where you might need to tweak or customize the properties for easier editing.
Similarly, TypeConverter
can be used when setting property values in the designer.
While these classes are exteremely useful, it is only in situations where you are working with code that already uses and understands them, therefore...
This change is visible only to code that also uses
TypeDescriptor
to retrieve the attributes. In my experience, they are not used much in the runtime outside ofSystem.ComponentModel
and related namespaces, so specifically yourSerializableAttribute
example will not actually make the type serializable (it doesn't affectType.IsSerializable
). This may seem limited, but these classes are extremely useful once the whole system uses them (and it is a sort of standard way to extend arbitrary types).The change is also permanent, unless you remove the attributes or the associated provider.
The instance is equivalent to the one created before. In addition, both instances have
SerializableAttribute
, sinceTypeDescriptor.AddAttributes
has global effects.The confusion is the result of the fact that
TypeDescriptor.CreateProperty
does not actually create a property, merely a property descriptor from an existing property. Accesing it through the descriptor will simply modify the real property of the object.
All in all, TypeDescriptor
is used to describe a new system (components) using standard language (types, properties, events, attributes), but they are otherwise unrelated.
精彩评论