I want to declare something similar to this:
public class ImpostorClassWithAddedNotificationSupport<T> : T, ICustomTypeProvider, INotifyPropertyChanged where T : class
But I receive this error:
CS0689: Cannot derive from 'T' because it is a type parameter
I would like to dynamically add new property behavior (overwrite base properties) with my class. Each property of my class would call base class property then add notification to it. This way, everything would works fine in design but have additonal functionnality to the derived class. Kind of impersonnation to add more functionnalities.
Is there a way to dynamically overwrite a type in order to add functionalities (functionnality like for example Notification)? If yes, how? If no, why?
My initial intention is:
I try to do a FakeObject that mimics any object I'd like to edit. It would dynamically create all properties of any object it mimics. Then I could edit that "FakeObject" and if I want to cancel, I flush that fakeObject and my original object has never been modified (like a "Cancel" on any dialog). On "Ok", it would apply changes to the original object. It already works for a PropertyGrid because PropertyGrid use reflection behind to discover and read/write properties. But I want to use my class at design time with WPF and WinUI. The notification part is only a bonus that would come with it. Otherwise I have to write a "Copy constructor" or any similar copy mechanism and also I have to implement INotifyPropertyChanged on each and every classes. I would prefer to keep my classes "Plain" - POCO. I would saved all of that if I would be able to write my code as intented.
What I realise after I asked
It is not possible actually. I should ask Microsoft for a new feature.
CodePudding user response:
No, this cannot be implemented this way, as the compiler error indicates. Basically, generics let you write a class around that generic type without knowing much about it, except for maybe the constraints you put on it like where T : class. So its too many unknowns for the compiler. Keep in mind, a generic class can use generic types from things not in its assembly, like how List where List is in a MS assembly and Foo is in your custom assembly. Base classes need to be in a visible assembly to the derived class when its compiled.
You can see the MS docs here or a MS blog post here.
Good question, though. These types of questions really help flesh out the understanding of C# and OO and where its capabilities and limits are.
CodePudding user response:
This is simply not possible in .Net.
Since you have no idea what T
is you could not override any methods, nor call any methods on it. If you add an interface constraint to give you that possibility, you could just inherit from that interface instead and create a regular decorator.
So I assume you would want some kind of template to wrap each method from the type you want to decorate, to provide things like logging. And this concept would likely need significant changes in the IL format and runtime to support.
A possible workaround would be to use reflection to emit a new type dynamically at runtime. Another could be to use annotations to rewrite the IL code in an assembly to add additional functionality to methods. I believe this is the approach used by PostSharp.
CodePudding user response:
So what you actually want is something like this:
MyClass x = new AddNotificationSupport<MyClass>();
When AddNotificationSupport<>
implements decorator or proxy (never understood the difference between two). I think your best way to go is Castle.DynamicProxy project. Here is a great tutorial to learn how it works and what you can do with it: https://kozmic.net/dynamic-proxy-tutorial/