...
We
...
have
...
introduced
...
the
...
Parrot
...
class
...
hierarchy
...
on
...
the
...
wiki-page
...
...
...
...
...
...
...
...
...
...
...
...
.
...
For
...
the
...
following
...
example
...
we
...
use
...
only
...
the
...
base
...
class,
...
i.e.
...
Parrot
...
.
...
Note
...
that
...
Parrot
...
has
...
a
...
Say
...
(string
...
s)
...
method.
...
(What
...
would
...
a
...
parrot
...
class
...
be
...
without
...
a
...
Say
...
method?)
...
Code Block |
---|
public class Parrot
{
public virtual void Fly ()
{
Console.WriteLine ("Flapflap...");
}
public virtual void Whistle ()
{
Console.WriteLine ("<River Kwai March here>");
}
public virtual void Say (string s)
{
Console.WriteLine ("\"{0}\"", s);
}
}
{code}
|
This
...
natural
...
gift
...
of
...
language
...
can
...
be
...
exploited
...
to
...
teach
...
a
...
parrot
...
how
...
to
...
pretend
...
to
...
have
...
a
...
phone
...
conversation.
...
The
...
mixin
...
class
...
OnThePhoneMixin
...
and
...
its
...
IOnThePhoneMixin
...
interface
...
have
...
two
...
methods:
...
PretendToTalkOnThePhone
...
()
...
- (uses
...
Say
...
(string
...
s)
...
- )
Wait (int
...
milliseconds)
...
(The
...
Wait
...
method
...
is
...
important
...
here,
...
because
...
it
...
makes
...
the
...
illusion
...
of
...
a
...
party
...
talking
...
at
...
the
...
other
...
side
...
of
...
the
...
connection
...
more
...
convincing
...
– many
...
stage-
...
and
...
movie
...
actors
...
don't
...
know
...
this,
...
by
...
the
...
way).
...
By
...
virtue
...
of
...
the
...
Parrot
...
in
...
the
...
generic
...
Mixin<Parrot>
...
declaration,
...
the
...
mixin's
...
PretendToTalkOnThePhone
...
method
...
can
...
access
...
Parrot
...
's
...
Say
...
method
...
via
...
the
...
This
...
property.
...
The
...
mixin
...
declaration
...
looks
...
like
...
this:
...
As you see, the class name Parrot
is used twice
- as type parameter for the generic
Mixin<TThis>
base class - as parameter to the
Extends
attribute
It is important not to confuse the two. As parameter for Mixin<TThis>
, Parrot
specifies which properties will be available via This
at compile time. As type for Extends
, Parrot
specifies that the OnThePhoneMixin
mixin extends the Parrot
class.
Usage of the mixed class is straightforward:
Code Block |
---|
// you must force the .NET runtime to load a reference to the
// Remotion.dll assembly. Otherwise the compiler will remove the
// facilities for loading the Remotion.dll assembly and your application
// will throw a type initializer exception, because it can't load it.
// The easiest way to touch the assembly is to use the IMixinTarget
// identifier:
FrameworkVersion.RetrieveFromType (typeof (IMixinTarget));
Console.WriteLine ("Parrot:");
var myPetParrot = ObjectFactory.Create<Parrot> (ParamList.Empty);
((IOnThePhoneMixin) myPetParrot).PretendToTalkOnThePhone (); // how cute!
myPetParrot.Whistle (); // back to normal
{code}
h6. Sample code
The sample code for this exercise is located [in subversion|https://svn.re-motion.org/svn/Remotion-Contrib/Samples/Mixin/WikiSamples/trunk/WikiSamples.ParrotMixinClass/Program.cs]
h5. Alternative: pass the interface
If we had an {{IParrot}} interface with a {{Say}} method, we could also use that interface for the {{TThis}} parameter, because {{This}} would provide access to the {{IParrot}} interface:
!Parrot.This.Interface.png!
Again, the {{TThis}} parameter does NOT influence on which target class the mixin class extends. It specifies where the members visible in {{This}} come from.
What's interesting here is that no connection between {{IParrot}} and {{Parrot}} is required. It does not hurt if {{Parrot}} is declared to actually implement {{IParrot}}, but it is NOT required. It suffices when the methods accessed via the {{This}} property share the same name and signature with those implemented in the target class (as specified in the {{Extends}} attribute, NOT in {{TThis}} parameter).
Matching interface members and {{This}} members is not done via static compilation, it is done by reflection. We will return to this point on the wiki-page [re-motion mixins basics -- duck typing].
h6. Sample code
The sample code for the alternative discussed here can be [in subversion|https://svn.re-motion.org/svn/Remotion-Contrib/Samples/Mixin/WikiSamples/trunk/WikiSamples.ParrotMixinInterface/Program.cs]
h5. Under the hood
- [under the hood of re-motion mixins -- mixins based on 'Mixin-TThis'] |
...
Sample code
...
The sample code for this exercise is located in subversion
Alternative: pass the interface
If we had an IParrot
interface with a Say
method, we could also use that interface for the TThis
parameter, because This
would provide access to the IParrot
interface:
Again, the TThis
parameter does NOT influence on which target class the mixin class extends. It specifies where the members visible in This
come from.
What's interesting here is that no connection between IParrot
and Parrot
is required. It does not hurt if Parrot
is declared to actually implement IParrot
, but it is NOT required. It suffices when the methods accessed via the This
property share the same name and signature with those implemented in the target class (as specified in the Extends
attribute, NOT in TThis
parameter).
Matching interface members and This
members is not done via static compilation, it is done by reflection. We will return to this point on the wiki-page re-motion mixins basics -- duck typing.
...
Sample code
...
The sample code for the alternative discussed here can be in subversion