Is there a way for me to change the properties a class has (add/remove properties) on runtime?
You cannot do this unless you are working with an instance of ExpandoObject. The metadata for a CLR type is fixed in the assembly and cannot be changed at execution time. If you really need this kind of dynamic behavior you must use a dynamic type (like EpandoObject) that supports this behavior.
Just to add to Andrew Hare's reply: With C# 4 and .NET 4 you can inherit from DynamicObject and redefine what it means to take various actions on an instance of the type. DynamicObject defines a number of virtual methods that you can override to take control of what it means to e.g. access a property. You could use this to allow properties to be added/removed to the instance, which is pretty much what ExpandoObject does.
For more about ExpandoObject see this question and this blog post.
You could create your types at runtime using System.Reflection.Emit -link
For UI development (i.e. what is presented to the end user) look at implementing ICustomTypeDescriptor (in System.ComponentModel). Many controls are aware of this interface and will use it to query the properties an instance or type exposes.
If you are on 3.5 you can use IL to create a dynamic type, and also accomplish the task, but it's a lot harder, but there are some frameworks for doing that I suppose.
Related
I was looking at the metadata for Type, and noticed a member was protected, which made me wonder what might derive from it, which made me realize I could write a class that derives from it, and all that makes me wonder what I can do with that (if anything).
No compiler error from following:
class MyType : Type
{
// Implemented abstract members here.
}
Great question. I only have a partial answer. There are currently 4 classes that derive from Type. You can find the Type hierarchy on MSDN.
System.Object
System.Reflection.MemberInfo
System.Type
System.Reflection.Emit.EnumBuilder
System.Reflection.Emit.GenericTypeParameterBuilder
System.Reflection.Emit.TypeBuilder
System.Reflection.TypeDelegator
It looks like those types are basically used to encapsulate some "instance-building" logic. But I haven't explored the code.
Edit
Oh, wow... that's interesting. The code examples seem to not only be creating instances of types, but also classes themselves. Therefore, some of these classes are creating CLR types, and saving them off to real assemblies. That's pretty cool.
Edit Again
Some of the big dogs have said that there are more than the four types I listed above. I used Reflector ReSharper to find the derived types and found these (there could still be types missing):
System.Type
System.RuntimeType
System.ReflectionOnlyType
System.Reflection.Emit.EnumBuilder
System.Reflection.Emit.GenericTypeParameterBuilder
System.Reflection.Emit.SymbolType
System.Reflection.Emit.TypeBuilder
System.Reflection.Emit.TypeBuilderInstantiation
System.Reflection.TypeDelegator
Edit Once More
as #MarcGravell stated, there's really no reason why you would want to derive a class from any of these. You could, however, use them within a class of your own to encapsulate your own logic.
Yeah, don't inherit from that ;p There are things like RuntimeType etc - Type is the abstraction you should usually use. If you want to represent a type dynamically at runtime, there are 2 main options;
in 4.0, dynamic (via implementing IDynamicMetaObjectProvider)
before that, TypeDescriptor (via implementing ICustomTypeDescriptor or providing a TypeDescriptionProvider, and possibly a TypeConverter)
If you want to do meta-programming (creating actual new types at runtime, rather than spoofing it), there is also TypeBuilder
Type is unsealed because it's actually designed to be inherrited from by the runtime. There are many examples of this in the BCL
EnumBuilder
RuntimeType
TypeBuilder
The most interesting of these, IMHO, is RuntimeType This is how a good majority of the Type instances in a running system are implmented. Most calls to o.GetType() will actually return a RuntimeType instance.
I'm using a 3rd party lib to do some work. I'm passing an object to the lib and it performing some actions on each property of the object. It enumerates properties using reflection. This is how it implemented and I can't change it.
I don't know which and how many properties should be processed by the lib at compile-time. This information only available at run-time. So I can't create class declaration in my source code.
It seems dynamic feature of .net4 can't help me because lib using reflection, not dynamic.
Actually I can see only two options here:
Create a huge class definition like this:
class Data
{
public object P1 {get; set;}
public object P2 {get; set;}
....
public object PN {get; set;} // N should be at least 10.000
}
Generate class definition at runtime and use CSharpCodeProvider to compile an use it.
Can you suggest me any other options?
And sadly, I can't replace this lib with another one.
Using the first approach will lead to high memory consumption. I would have chosen use TypeBuilder class to create new types at the runtime.
What you're looking for is known as a Property Bag. You may be able to implement something like this by using ICustomTypeDescriptor to expose additional metadata (assuming your library supports it).
If your consuming library is using Reflection directly (and not taking advantage of designer features like Type Descriptors) then your best bet is probably dynamic generation of a proxy wrapper with the additional properties. Castle DynamicProxy is one good way to do this.
EDIT:
Actually, I'm not sure if Castle supports adding new properties to the proxy object. You might be stuck using IL Emit directly via TypeBuilder. This is non-trivial, as you'll need to learn enough about IL Emit to generate the property accessors and there's a bit of a learning curve. That said, it's interesting and fun stuff and worth the effort if you have the time.
I guess it's about regular GUI element like Grid or PropertyGrid.
Then I would start from reflecting grid's method that accept class instance as parameter, and if it is possible fill internal Dictionary<PropertyInfo, instance> or Dictionary<Name,Value> with my own vales.
If this is impossible, instead of Emit, try to use System.CodeDom:
Link
Is there a way to do this:
class Example {
[ChangeNotification]
private int field;
}
Such that changing the value of "field" would automatically get logged, generate an event, etc?
No, attributes are type specific, not instance specific.
But you can implement INotifyPropertyChanged on all you objects and have some class listen to all the events and do the logging.
At first view, I would better recommend that you implement the INotifyPropertyChanged interface, as an Attribute is type specific.
You can do something similar (at least to a property, but not to a field) via Aspect oriented programming. However, this requires the use of a program like PostSharp, which actually rewrites the code inline based on the attribute.
Typically, this is used to implement INotifyPropertyChanged on a property. However, there are rewrite rules for logging and other features available.
This won't work for a field, however. It does work for a property, since the rewriter can add code to the property set method, but a field is handled directly by the CLR.
yes it's possible with postsharp using OnFieldAccessAspect
http://www.sharpcrafters.com/forum/Topic2244-4-1.aspx
I don't understand, why use dynamic MethodBags when I can use ExpandoObject? What am I missing here?
MethodBags and analogous implementations tend to have some limitations. It may be easier just to implement your own class if you find yourself running into these roadblocks. Specifically:
Hard to implement state in a method bag. (Expression trees cannot contain objects that are statically typed as dynamic; no good syntax to create methods that rely on internal state on the same dynamic object.)
Can only add public methods. No virtual, private, protected, or abstract methods.
Can't implement an interface.
In comparison, ExpandoObjects are true classes and are much richer and more full-featured. They more closely mimic what you'd otherwise get for free in, say, Ruby or Python.
Quick note: for those who don't know, dynamic method bag is a technique for adding methods dynamically to an object. Bill Wagner describes it here with source code here.
The simple answer is that the MethodBag concept is just showing you a technique. You can absolutely use the ExpandoObject to do this, but there may be a time when you want to write your own class that inherits from System.Dynamic.DynamicObject. An example of this might be to provide a dynamic JSON, YAML, or XML object that lets you reference your data in dot-properties-notation rather than in the traditional stringy ways. If you inherit from DynamicObject, you may find that you want to allow the addition of dynamic functions to your class too. The MethodBag technique shows you how to do that. The ExpandoObject is just one example of a class that implements this technique. ExpandoObject will be good for 95% of what you need, and the MethodBag technique shows you how to custom write your own when you decide to do that for the last 5%.
Is there any way to add Field (or FieldInfo, maybe this is the same) to a class at runtime?
You can't alter a class definition at runtime. However, you can create a new class that inherits from the original class (if it's not sealed) and declares the field. You can do this by emitting the appropriate IL code using System.Reflection.Emit.
No, C# doesn't allow monkey-patching.
You can generate new classes using either CodeDOM or Reflection.Emit, but you can't modify existing ones.
C# does not allow it because all of it's classes are based on Metadata. The CLR (not C#) disallows the adding of fields to metadata at runtime (1). This is the only way that C# would be able to add a field at runitme.
This is unlike dynamic langauges such as IronPython which essentially don't have concrete metadata classes. They have more dynamic structures which can be altereted at runtime. I believe IronPython simply keeps it's members (fields and methods) in what amounts to a hashtable that can be easily altered at runtime.
In C# 3.0, your best resource is to use Reflection.Emit. But this will generate an entirely new class vs. altering an existing one.
(1) There are certain APIs such as the profiling APIs or ENC that allow this but I'm not sure if their capabalities expand to adding fields.
See this question for a simple way to do it in C# 4.0, by casting an ExpandoObject as an IDictionary, which causes the values added to the dictionary to become properties of the object. I demonstrate this in another answer of mine showing that they actually become properties.
However, this is only possible with an instance of ExpandoObject or by sub-classing DynamicObject.
It may also be possible to use with other classes if they implement IDynamicMetaObjectProvider, but I think there is too much work involved to get it to work properly.
Not exactly.
However, you can implement ICustomTypeDescriptor to approximate it, and then just use a hashtable to store the fieldname/value pairs. A lot of the framework which uses reflection asks for ICustomTypeDescriptor first.
Not until C# 4.0 which adds dynamic lookup and is based on the CLR 4.0 which incorporates the DLR, and then it will not strictly be adding to a class, as classes won't be in the picture.
as others already said, this isn't possible. What is the reason for your question? If you need to store some additional data in the class dynamically, then you could probably just use dictionary:
class My {
Dictionary<string, object> data;
public My() { data = new Dictionary<string, object>(); }
}
.. but it really depends on what you actually want to achieve?
Perhaps you could use the Decorator pattern.
In object-oriented programming, the decorator pattern is a design pattern that allows behavior to be added to an individual object, either statically or dynamically, without affecting the behavior of other objects from the same class.
http://www.dofactory.com/Patterns/PatternDecorator.aspx