Re: OOP Aggregation

Tech-Archive recommends: Repair Windows Errors & Optimize Windows Performance

From: John Wood (j_at_ro.com)
Date: 06/29/04


Date: Mon, 28 Jun 2004 22:52:14 -0400

Yeah events are an option, but that sounds awfully like another
manifestation of the decorator pattern. Although it does have the benefit of
multicasting, but then I suppose you have to worry about the order in which
the delegates are invoked and such.

I agree that creating the proxy at runtime is an option -- and probably what
.net languages like Smalltalk and Eiffel would do to emulate some of the OOP
features not directly supported in the CLR.

Also, another idea I had, would be to use the contextboundobject features of
the CLR, intercepting method calls and giving 'plugins' a chance to handle
the method. The only problem is that the whole remoting infrastructure adds
significant performance penalties (method calls become something like 100
times slower), and wouldn't work on MBV objects, so it's not really an
option in serious apps.

And the biggest problem I have with the decorator pattern is that you lose
all of the class hierarchy parenthood of the object that the proxy is
encapsulating, so it's hardly a transparent solution.

Maybe I'll investigate some of the runtime reflection/codedom features to
see what kind of runtime options I might have for doing this
programmatically.

Thanks.

-- 
John Wood
EMail: first name, dot, last name, at priorganize.com
"Niki Estner" <niki.estner@cube.net> wrote in message
news:eZooNtWXEHA.1356@TK2MSFTNGP09.phx.gbl...
> They probably thought that many common applications of the decorator
pattern
> could be easily solved using events. (Add functionality at runtime by
> overriding some event) Also, delegates are a lot cleaner and simpler than
> good ol' function pointers, and if your "mother objects" contained
> replaceable delegates instead of virtual functions, the kind of
> "runtime-inheritance" you had in mind would be easily possible. If the
> object's clients only access the object by a well-defined set of
interfaces,
> you could only replace one of those interfaces, leaving the others
> unchanged, and introduce new behaviour this way.
> Of course, all these solutions (which are the typical C# solutions)
require
> provisions on the parent class side, and some special design on the client
> side.
> Thanks to IL it's quite easy nowadays to create code at runtime, so
creating
> some proxy class on-the-fly from metadata would be entirely possible, too.
>
> So, in the end I still think you have plenty of options to choose from;
And
> I do remember good old windows-message-handlers that did all kinds of
"dirty
> tricks" to re-route messages at runtime. That is, I do remember all those
> debugging sessions...
>
> Niki
>
> "John Wood" <j@ro.com> wrote in
> news:%23HWBOLVXEHA.1144@TK2MSFTNGP10.phx.gbl...
> > Thanks for your thoughts.
> >
> > A long time ago I implemented something very hacky in COM where I would
> > synthetically add support for new interfaces into an existing instance
> (that
> > didn't support aggregation). Sounds similar to your suggestion re
> > reflection... I think I've matured enough not to try anything like that
> > again! :)
> >
> > It's true, the decorator pattern is the most common (and probably best)
> > solution available today -- but it does seem like a common and
legitimate
> > problem that would warrant native support in a popular language such as
> C#.
> >
> > I really don't like the idea of manually delegating each method, because
> (a)
> > you lose the ability to cast to base classes of the original
> implementation
> > and (b) you have to maintain those delegates and keep the, in sync.
> >
> > In my mind, it's one of the biggest stumbling blocks of an extensible
> object
> > oriented system.  You create classes, you want to allow other vendors to
> > 'plug-in' their extensions in the form of derived classes so they can
> > override various bits of functionality, but the 'plugging in' doesn't
> occur
> > until after instantiation when it's too late.
> >
> > But there just isn't a way to do this neatly in C# (or C++ for that
> matter).
> > I think we really need native support for the decorator pattern in C#.
> >
> > -- 
> > John Wood
> > EMail: first name, dot, last name, at priorganize.com
> > "Niki Estner" <niki.estner@cube.net> wrote in message
> > news:%23W1dJ$UXEHA.3476@tk2msftngp13.phx.gbl...
> > > Let's assume for a moment we were real IL-assembler cracks and could
> bend
> > > the CLR in any way we wanted: We could (in theory) reallocate the
> instance
> > > of the old class we're given to make room for the additional members
in
> > the
> > > new class and modify the virtual function table pointer, and the
> interface
> > > pointers and metadata pointers to point to the new classes ones. If I
> got
> > > you right, that's roughly what you had in mind?
> > > First of all: This is (almost) possible. You could simply allocate an
> > > instance of the new class, and copy each member (using reflection)
from
> > the
> > > old class into the new one. Modify all pointers to the old instance to
> > point
> > > to the new one (probably the ugliest part) and you're done.
> > > There are major drawbacks in this approach, namely that it's hard to
> > > identify all pointers to the old instance (think of locks or event
> > > subscriptions) and that you don't really know the internal state of
the
> > > "old" object when you "apply" your new class.
> > > For your second question: COM had a concept called "aggregation" in
> which
> > a
> > > COM object could expose some other object's interfaces transparently
as
> if
> > > they were it's own ones, btu I don't know how to recreate that in the
> .net
> > > environment.
> > > I think I read somewhere that Smalltalk supported something like you
> > > suggested, but that's all i know about it - maybe you can get some
ideas
> > > from looking at that language.
> > > IMO the idea behind a OOP language *is* to restrict what is possible
on
> > > objects/classes/interfaces; Otherwise we could all build C structures
> with
> > > function pointers - you could do *anything* with those...
> > >
> > > That said, the decorator pattern (which you described) is probably by
> far
> > > the most common and reliable solution to this problem.
> > >
> > > Niki
> > >
> > > "John Wood" <j@ro.com> wrote in
> > > news:%23jPdOCUXEHA.4032@TK2MSFTNGP11.phx.gbl...
> > > > Let's say you're provided with an instance of a class. The
> instantiation
> > > > takes place in another module that you have no control over.
> > > >
> > > > However, you've extended that class with your own value-added
> > > functionality.
> > > >
> > > > In C#, given such an instance, and a derived class, there's no way
to
> > > > 'attach' the instance to the class -- you have to either change the
> way
> > > the
> > > > class was instantiated (not possible in this case), or wrap the
class
> > and
> > > > delegate each function (a concept known as aggregation).
> > > >
> > > > I'm sure I've asked this question on the group before, and I settled
> for
> > > > aggregation. But I just don't like it.
> > > >
> > > > I was wondering if anyone had any thoughts on this... ideas of more
> > > elegant
> > > > work-arounds / design patterns... solutions in other languages etc.
> > > >
> > > > Thanks.
> > > >
> > > > -- 
> > > > John Wood
> > > > EMail: first name, dot, last name, at priorganize.com
> > > >
> > > >
> > >
> > >
> >
> >
>
>


Relevant Pages

  • [PATCH] Documentation cleanup: trivial misspelling, punctuation, and grammar corrections.
    ... Different DMA engines may support different number of domains. ... +- API for paravirt ops for abstracting functionality for VMM folks. ... Read/Write attribute file that controls memory scrubbing. ... + Further information can be found in the interfaces section below for ...
    (Linux-Kernel)
  • [PATCH] Documentation cleanup: trivial misspelling, punctuation, and grammar corrections.
    ... Different DMA engines may support different number of domains. ... +- API for paravirt ops for abstracting functionality for VMM folks. ... Read/Write attribute file that controls memory scrubbing. ... + Further information can be found in the interfaces section below for ...
    (Linux-Kernel)
  • Re: OOP Aggregation
    ... synthetically add support for new interfaces into an existing instance (that ... didn't support aggregation). ... override various bits of functionality, but the 'plugging in' doesn't occur ... > pointers and metadata pointers to point to the new classes ones. ...
    (microsoft.public.dotnet.languages.csharp)
  • Re: OOP Aggregation
    ... delegates are a lot cleaner and simpler than ... object's clients only access the object by a well-defined set of interfaces, ... > didn't support aggregation). ... > override various bits of functionality, ...
    (microsoft.public.dotnet.languages.csharp)
  • Re: Extend or Decorate?
    ... > extend an existing class or use the decorator pattern when adding ... The Decorator Pattern is used for adding additional functionality to a ... is impossible to extend a single object this way. ... you can add functionality to a single object and leave others like ...
    (comp.lang.java.programmer)