tags:

views:

160

answers:

4

I have a constructor question for C#.

I have this class:

public partial class Signature : Form, ISignature
{
    private readonly SignatureMediator mediator;

    public Signature(SignatureMediator mediator)
    {
        this.mediator = mediator;
        InitializeComponent();
    }

    .... more stuff
 }

I want to construct this class like this:

    public SignatureMediator(int someValue, int otherValue, int thirdValue)  
       : this(new Signature(this), someValue, otherValue, thirdValue)
    // This is not allowed --^
    {
        // I don't see anyway to get this in to the ":this" part.
        //Signature signature = new Signature(this);

    }            


    public SignatureMediator(ISignature form, int someValue, int otherValue, int thirdValue)
    {
        SigForm = form;
        SomeValue= someValue;
        OtherValue= otherValue;
        ThirdValue= thirdValue;
    }

The : this( new SignatureThis(this) is not allowed (the this used in the constructor is not allowed).

Is there anyway to set this up without duplicating the assignment of the int values?

A: 

You can't call "this" as an argument to the same since the object isn't constructed. Instead you would have to chain your construction:

public SignatureMediator(int w, int x, int y, int z)  
   : this(x,y,z)
nick
+4  A: 

How about making the second constructor construct a Signature from this if the ISignature parameter is null, otherwise using the provided ISignature? You could then pass null from the first constructor to get the behavior you want.

public SignatureMediator(int someValue, int otherValue, int thirdValue)  
   : this(null, someValue, otherValue, thirdValue)
{
}            

public SignatureMediator(ISignature form, int someValue, int otherValue, int thirdValue)
{
    if (form == null)
    {
        SigForm = new Signature(this);
    }
    else
    {
        SigForm = form;
    }

    SomeValue = someValue;
    OtherValue = otherValue;
    ThirdValue = thirdValue;
}
Zach Johnson
+2  A: 

You definitely cannot use this inside the constructor chaining call, so you'll have to call it in the body of the constructor. The cleanest way would be to extract the common initialisation code into a separate method, like this:

public SignatureMediator(int someValue, int otherValue, int thirdValue)  
{
    Initialise(someValue, otherValue, thirdValue)
    SigForm = new Signature(this);
}            


public SignatureMediator(ISignature form, int someValue, int otherValue, int thirdValue)
{
    Initialise(someValue, otherValue, thirdValue)
    SigForm = form;
}

private void Initialise(int someValue, int otherValue, int thirdValue)
{
    SomeValue= someValue;
    OtherValue= otherValue;
    ThirdValue= thirdValue;
}

If constructing a Signature object is really cheap you could avoid the extra method and just have the second constructor call the first one, before overwriting the SigForm value it creates with the passed-in value.

Evgeny
The downside of the constructors calling an initialize method is that SomeValue, OtherValue, and ThirdValue can't be declared readonly and be initialized in a method other than a constructor--only a problem if you otherwise want them readonly. Your example could probably be tweaked to make that common init be a private constructor, which would avoid that caveat in general.
Rob Parker
@Rob Parker - quite right, if that was an issue you could have a private constructor with a dummy argument just to give it a difference signature from the other public one.
Evgeny
+1  A: 

I've never seen a Mediator responsible for constructing the objects that it mediates between. If it were, it would be mixing up creational concerns with mediation, which seems ugly even without your syntactic challenge.

Why not pass the mediator to the Signature in the manner that the classic GoF pattern suggests? Your clients construct the mediator, then they pass the mediator to the constructors of each of the objects the mediator mediates between. If that's too error-prone, your objects can be built using Builder or, perhaps, factory methods.

JasonTrue
Good point. I admit to not being sure of what I am doing with this pattern.
Vaccano