Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.
Comment: Migrated to Confluence 4.0

...

Mixin

...

scopes

...

are

...

useful

...

for

...

mixing

...

at

...

run-time

...

and

...

limiting

...

the

...

"reach

...

of

...

action"

...

for

...

certain

...

mixins.

...

If

...

nothing

...

else,

...

this

...

is

...

eminently

...

useful

...

for

...

testing.

...

This

...

page

...

explains

...

how

...

to

...

construct

...

and

...

use

...

mixin

...

scopes.

...

The

...

Hotel

...

mixin

...

sample

...

's

...

Hotel.Tests

...

project

...

makes

...

good

...

use

...

of

...

transaction

...

scopes

...

for

...

testing.

...

In

...

the

...

previous

...

example,

...

we

...

have

...

made

...

an

...

entirely

...

home-grown

...

configuration

...

the

...

active

...

configuration

...

for

...

the

...

entire

...

thread.

...

For

...

the

...

following

...

example,

...

we

...

will

...

introduce

...

three

...

modifications

...

to

...

that

...

idea.

...

  1. We

...

  1. will

...

  1. derive

...

  1. our

...

  1. custom

...

  1. configuration

...

  1. from

...

  1. the

...

  1. existing

...

  1. default

...

  1. master

...

  1. configuration

...

  1. (which

...

  1. in

...

  1. turn

...

  1. is

...

  1. a

...

  1. reflection

...

  1. of

...

  1. all

...

  1. the

...

  1. Extends

...

  1. and

...

  1. Uses

...

  1. attributes

...

  1. in

...

  1. the

...

  1. application).

...

  1. Instead

...

  1. of

...

  1. adding

...

  1. to

...

  1. that

...

  1. configuration,

...

  1. we

...

  1. will

...

  1. remove

...

  1. from

...

  1. it

...

  1. with

...

  1. SuppressMixin<>

...

  1. .

...

  1. We

...

  1. will

...

  1. make

...

  1. the

...

  1. custom

...

  1. configuration

...

  1. active

...

  1. within

...

  1. a

...

  1. limited

...

  1. scope

...

  1. ,

...

  1. i.e.

...

  1. temporarily.

...

Since

...

the

...

simplistic

...

dessert

...

wax

...

sample

...

does

...

not

...

lend

...

itself

...

very

...

well

...

to

...

our

...

sophisticated

...

endeavor,

...

we

...

will

...

resort

...

to

...

the

...

slightly

...

more

...

advanced

...

parrot

...

on

...

a

...

unicycle

...

here.

...

The

...

following

...

sample

...

is

...

based

...

on

...

the

...

class

...

hierarchy

...

of

...

parrots

...

from

...

the

...

page

...

re-motion

...

mixins

...

basics

...

--

...

what

...

about

...

sub-classes

...

of

...

the

...

target

...

class?

...

[ Parrot, GreyParrot and Macaw, with Parrot being the base class for GreyParrot and Macaw. ]

The entire hierarchy is extended by the CircusMixin which gives the entire hierarchy the ability to ride a unicycle. This configuration is read in and made the master configuration, which in turn is the active configuration for the given task.

Since we can't modify an existing configuration, we have to build a new one based upon the active configuration and make the active configuration for our thread.

As explained on page re-motion mixins basics -- what about sub-classes of the target class? the entire class hierarchy is extended by a mixin if that mixin is applied to the base class. In our example, we will exempt the Macaw class from being mixed. The new methods in the following snippet are

  • MixinConfiguration.BuildFromActive () – clones the active configuration
  • SupressMixin<> () – removes the specified mixin from the given class
Code Block
var t = typeof (IMixinTarget);

var myMixinConfiguration = MixinConfiguration.BuildFromActive () // build upon active configuration
 .ForClass<Macaw> ().SuppressMixin<CircusMixin> ()               // remove the circus mixin from the 'Macaw' class
 .BuildConfiguration ();                                         // finish construction 
{code}

At

...

this

...

point

...

we

...

have

...

a

...

new

...

mixin

...

configuration

...

in

...

the

...

myMixinConfiguration

...

variable.

...

It

...

is

...

exactly

...

like

...

the

...

default

...

master

...

configuration

...

that

...

has

...

been

...

assembled

...

from

...

inspection

...

of

...

the

...

executable.

...

In

...

the

...

default

...

master

...

configuration,

...

the

...

CircusMixin

...

is

...

applied

...

to

...

Parrot

...

,

...

GreyParrot

...

and

...

Macaw

...

.

...

In

...

our

...

improved

...

clone,

...

the

...

CircusMixin

...

is

...

only

...

applied

...

to

...

Parrot

...

and

...

GreyParrot

...

.

...

Note

...

that

...

we

...

haven't

...

made

...

the

...

configuration

...

active

...

yet.

...

Remember

...

that

...

we

...

want

...

to

...

do

...

it

...

temporarily,

...

not

...

for

...

the

...

entire

...

life-time

...

of

...

the

...

thread.

...

For

...

this,

...

we

...

have

...

to

...

create

...

a

...

mixin

...

configuration

...

scope

...

from

...

myMixinConfiguration

...

.

...

You

...

do

...

this

...

with

...

the

...

method

...

EnterScope

...

:

...

}
Code Block
... some configuration is active here ...
using (myMixinConfiguration.EnterScope ())
{
  ... code code code ...
  ... where 'myMixinConfiguration' is active ...
} // end of scope

... previous mixin configuration is active again ...
{code}

The {{using}} spans the _scope_ for which the configuration is active. As soon as execution of the code passes the closing bracket {{\}}} of the {{using}}, the cloned configuration vanishes and the previous configuration becomes active again. (People who know the PhoneBook tutorial will recognize this mechanism: this is how [re-store]s _transaction scopes_ work.)

You can even nest such scopes to arbitrary depth:

{code}

The using spans the scope for which the configuration is active. As soon as execution of the code passes the closing bracket } of the using, the cloned configuration vanishes and the previous configuration becomes active again. (People who know the PhoneBook tutorial will recognize this mechanism: this is how re-stores transaction scopes work.)

You can even nest such scopes to arbitrary depth:

Code Block
... configuration A is active here ...
using (mixinConfiguration_B.EnterScope ())
{
  ... code code code ...
  ... where 'mixinConfiguration_B' is active ...

  using (mixinConfiguration_C.EnterScope ())
  {
    ... code code code ...
    where 'mixinConfiguration_C' is active ...
  } // end of scope for mixinConfiguration_C
  ... mixinConfiguration_C is active again ...

} // end of scope for mixinConfiguration_B
{code} 

The following code sample utilizes {{using}} for our special configuration that has mixing for {{Macaw}} suppressed. 

{code}

The following code sample utilizes using for our special configuration that has mixing for Macaw suppressed.

Code Block
  class Program
  {
    static void Main (string[] args)
    {
      // mind the loading of 'Remotion.dll'!
      var t = typeof (IMixinTarget);

      var myMixinConfiguration = MixinConfiguration.BuildFromActive ()   // clone the currently active configuration 
                                                                         // (that happens to be the master default config 
                                                                         // at this point)
        .ForClass<Macaw> ().SuppressMixin<CircusMixin> ()                // remove the mixing of the circus mixin from the 'Macaw' class
        .BuildConfiguration ();                                          // cause the actual building of our clonee 

      // now we span a scope for our special configuration
      using (myMixinConfiguration.EnterScope ())
      {
        // The mixed parrot class works as usual, no suppression here
        var myCircusParrot = ObjectFactory.Create<Parrot> (ParamList.Empty);
        Console.WriteLine ("Parrot:");
        myCircusParrot.Whistle();
        ((ICircusMixin) myCircusParrot).RideUniCycle();
        Console.WriteLine();

        // The mixed grey parrot class works as usua, no suppression here either
        Console.WriteLine ("GreyParrot:");
        var myCircusGreyParrot = ObjectFactory.Create<GreyParrot> (ParamList.Empty);
        myCircusGreyParrot.DestroyFurniture();
        ((ICircusMixin) myCircusGreyParrot).RideUniCycle();
        Console.WriteLine();

        // The macaw can do as macaws do (crack nuts)...
        Console.WriteLine ("Macaw:");
        var myBogusCircusMacaw = ObjectFactory.Create<Macaw> (ParamList.Empty);
        myBogusCircusMacaw.CrackNut();
        try
        {
          // ... but it can't ride the unicycle, because that's been
          // suppressed
          ((ICircusMixin) myBogusCircusMacaw).RideUniCycle ();
        }
        catch (InvalidCastException)
        {
          // ... what gives us a bummer at run-time
          Console.WriteLine ("... or not. We caught an 'InvalidCastException'.");
          Console.WriteLine ("The 'Macaw' class can't be cast to 'ICircusMixin'");
          Console.WriteLine ("because we suppressed that mixin. (Remember?)");
        }
        
        Console.WriteLine();
      } // end of scope with the non-unicycle macaw

      // at this point, the original (default master) configuration
      // is active again, so the macaw CAN ride the unicycle
      Console.WriteLine ("Macaw:");
      var myWorkingCircusMacaw = ObjectFactory.Create<Macaw> (ParamList.Empty);
      myWorkingCircusMacaw.CrackNut ();
      ((ICircusMixin) myWorkingCircusMacaw).RideUniCycle ();
      Console.WriteLine ();

      Console.ReadLine ();
    }
  }
{code}

If

...

you

...

need

...

the

...

new

...

configuration

...

only

...

once,

...

you

...

can

...

directly

...

call

...

EnterScope

...

on

...

the

...

builder

...

without

...

using

...

BuildConfiguration

...

.

...

BuildConfiguration

...

is

...

useful

...

when

...

you

...

need

...

to

...

store

...

the

...

configuration

...

in

...

a

...

variable

...

in

...

order

...

to

...

use

...

it

...

more

...

than

...

once.

...

Sample code

You find the complete sample code for this exercise in subversion

A more elaborate, and common, application of mixin scopes can be found in the unit-tests of the Hotel mixin sample, discussed there.