Reputation: 181
I am modifying some code that sits between two established layers, and am having trouble figuring out what the best design is.
Currently the code calls a file access library, and returns an object to the caller. I need to extend the returned object to add some custom dispose functionality. I don't have access to the definitions of the passed objects (some are filestreams, for example)
It would save me a lot of work if I could create a child instance that behaves like a base instance, and can be created from a base instance, but that has some hidden extra functionality. Can this be done without knowing the implementation details of the base class?
In code form that looks a lot like this:
private class FileObjectWithDispose : FileObject, IDisposable
{//voidaction is a delegate, this is .net 2.0
private VoidAction _disposeCallback;
public static FileObjectWithDispose wrapFile(FileObject unWrappedFile, VoidAction DisposeAction)
{//Implementation missing, this is the crux of what I don't know how to do
FileObjectWithDispose wrappedFile = new FileObjectWithDispose(unWrappedFile);
wrappedFile._disposeCallback = DisposeAction;
return wrappedFile;
}
private FileObjectWithDispose()
: base(null, null)//base class does not have a default constructor
{
throw new NotImplementedException("FileObjectWithDispose is a wrapper class which is intended only to be cast from a filestream.");
}
private void Dispose()
{
_disposeCallback();
base.Dispose();
}
}
a sample call would look like this:
Connect(file, username, password, domain);
return FileObjectWithDispose.wrapFile(OpenFile(path), () => { Disconnect(file, username); });
The key difficulty I'm having is, if it's possible, how do I take a base class instance and create a decorated instance if the base class does not implement an interface that allows itself to be decorated? Any ideas how to accomplish this task?
Thanks!
Upvotes: 2
Views: 3503
Reputation: 625
The decorator pattern is the way to go.
ICustomDisposeAction
(an example name)Implement this interface with all those possible classes which on you would want to perform DisposeAction
on.
FileObjectWithDispose : FileObject, IDisposable, ICustomDisposeAction
Create another class Decorator which also implements ICustomDisposeAction
. Pass the original base class through the constructor of the decorator and then call the decorator's DisposeAction
on it.
public class Decorator : ICustomDisposeAction { public FileObject wrappedFile { get; set; } public Decorator(FileObject unWrappedFile,...) { wrappedFile = unWrappedFile; //Do your custom dispose here } }
Hope this helps.
Upvotes: 6