views:

75

answers:

6

Is it possible to add a custom property to an object that is part of the .NET framework?

I know how I would do this if I was just giving a class i'd wrote a property, but what about adding a custom property to the FileSystemWatcher class?

I'm loading in the Path I want to watch from an XML file, but also want to add a property to store more information, in this case the location of a config file. Can I add this property to the FileSystemWatcher class itself?

+8  A: 

So you want to inherit all the functionalities of the FileSystemWatcher, while adding your properties? Try inheriting the class:

public class MyFileSystemWatcher : FileSystemWatcher
{
    public string XmlConfigPath { get; set; }
}

and after that you can use your new class on every place where you would use the System.IO.FileSystemWatcher, like this:

MyFileSystemWatcher fsw = new MyFileSystemWatcher();
fsw.XmlConfigPath = @"C:\config.xml";
fsw.Path = @"C:\Watch\Path\*.*";

Another approach would be to make a class that will both have the config file location , and the FileSystemWatcher object as a property, along these lines:

public class MyFileSystemWatcherManager
{
    public string XmlConfigPath { get; set; }
    public FileSystemWatcher Watcher { get; set; }

    public MyFileSystemWatcherManager()
    {
        Watcher = new FileSystemWatcher();
    }
}

and with usage like this:

MyFileSystemWatcherManager manager = new MyFileSystemWatcherManager();
manager.XmlConfigPath = @"C:\config.xml";
manager.Watcher.Path = @"C:\Watch\Path\*.*";

Composition is possible even when the base class cannot be inherited, and it's generally preferred from an OO perspective, since most of the code that uses your class will rely only on your class, and not on the base class. However, when you do want to inherit all of the base behaviours and just add some (well-defined) extras, inheritance is the simpler and more tightly-coupled solution.

SWeko
This is correct, but I wonder if inheritance is the right answer. I suspect that it might be a better fit to create a class that *has* a FileSystemWatcher without *being* one.
Steven Sudit
@Steven Sudit: For the above question, I think that inheritance is the correct approach, composition would end up ugly (either mimicking the FSW behaviour with pass-through, or allowing access to the FSW directly),
SWeko
Again, I don't know enough to say for sure, but my gut feeling is that a FSW that knows about a config file is doing something at a higher level. It's no longer a general-purpose FSW, and in fact may only use a limited subset of the functionality. As such, it might benefit from composition.
Steven Sudit
@Steven Sudit:FSW has a limited functionality to begin with :) However, composition could be a viable alternative, will edit my answer to reflect that...
SWeko
Then I'll toss in an upvote.
Steven Sudit
+1  A: 

Create a wrapper around the component you want to use.

thelost
A: 

What about creating your own class derived from FileSystemWatcher? Youll be free to add properties.

callisto
+1  A: 

Unfortunately, extension properties do not exist in c#. You need to create a child class that inherits FileSystemWatcher.

David
+1  A: 

I must admit that I don't really understand what you're trying to do, but you could possibly solve your problem like this:

public static class FileSystemWatcherExtensions
{
    public static Dictionary<string, string> MyProperty {get;set;}

    public static string GetMyProperty(this FileSystemWatcher watcher)
    {
        if (MyProperty != null && MyProperty.ContainsKey[watcher.GetHashCode()]) {
            return FileSystemWatcherExtensions.MyProperty[watcher.GetHashCode()];
        } else {
            return null;
        }
    }

    public static void SetMyProperty(this FileSystemWatcher watcher, string value)
    {
        if (MyProperty == null) {
            MyProperty = new Dictionary<string, string>();
        }
        FileSystemWatcherExtensions.MyProperty[watcher.GetHashCode()] = value;
    }
}
// I changed this example to allow for instance methods - but the naming can be
// improved...

This would create two extension methods that act as getter/setter for your property, that you use like so:

var fsw = new FileSystemWatcher();
fsw.SetMyProperty("a string");
var val = fsw.GetMyProperty(); // val == "a string"

This means you can still keep your syntax as if you're actually adding a property to the FileSystemWatcher class in that you're only calling on that class and not on your extension. However, you're really just wrapping yourself around a static property on an extension class.

Tomas Lycken
+1 for simulated extension properties. We might get them in the next C#, but until then, this is the best there is short of inheritance (and of course that's not an option with final classes)
SWeko
Nice idea, but this would support instance properties, which may or may be what the OP is after...
Matthew Abbott
@Matthew: Yes, I know this won't really behave as instance properties. However, short of inheritance, this was the only way I could come up with extending a class with properties. If it is necessary with instance properties, maybe you could let the static property be a hashtable, and use `GetHashKey` on the instances as keys?
Tomas Lycken
@Mattew: I updated the code example to allow for instance properties. However, this is depending on the GetHashKey a) not changing and b) being unique for each `FileSystemWatcher` instance, so I'm not sure how foolproof it is.
Tomas Lycken
A: 

An alternative to inheriting would be a wrapper class which decorates the target class. Check out the decorator pattern here

Peter Kelly
I am unclear on what the benefit of this approach would be.
Steven Sudit
If XmlConfigPath is the only property that will be added to the FSW, decoration is an overkill. However, if there are multiple of these properties, and several scenarios where they might or might not apply, by all means, check out the Decorator pattern, it can be a lifesaver.
SWeko
@SWeko: Thanks for your clarification. I suspected premature patternization here.
Steven Sudit
@Steven Sudit: I understood "premature patternization" to be attempting to apply a pattern at too early a stage of development i.e. while drawing a domain model. Here, when talking about code I thought it would be appropriate to mention the Decorator pattern as "wrapper" classes were being suggested. The Decorator is a wrapper but also benefits from being a well-recognized pattern - although I take your point about being overkill for 1 additional property, I still think if this was to be extended it would become beneficial very quickly.
Peter Kelly
While it's certainly appropriate to mention, I'm hesitant to jump on the pattern bandwagon. This may have less to do with the specifics here and more to do with my own biases due to being the victim of programmers who are more interested in following a recognized pattern than solving the problem at hand. Call me jaded about patterns, if you must.
Steven Sudit
@Steven Sudit: No, I totally agree. It is very frustrating to be up against that sort of mindset - fitting the problem into a pattern at all costs! I worked with someone who stubbornly applied MVP to every project he developed. But I just thought it might add value here. Anyways, definitely didn't think it was a case of "premature" patternization - if he was going to apply a pattern then now seems as good a time as any seeing as he's in the middle of coding :)
Peter Kelly
@Peter: Point taken, and I freely admit that I may well have overreacted due to my bad experiences.
Steven Sudit