1

How I can invoke private constuctors in public one? I'd like to public invoke from setter and from setter invoke objects initializer.

    private MyMailer() // objects initializer
    {
        client = new SmtpClient(SMTPServer);
        message = new MailMessage {IsBodyHtml = true};
    }

    private MyMailer(string from) //from setter
    {
        SetFrom(from);
    }

    public MyMailer(string from, string to, string cc, string bcc, string subject, string content)
    {
        foreach (string chunk in to.Split(new string[] {";"}, StringSplitOptions.RemoveEmptyEntries))
        {
            AddTo(chunk);    
        }

        foreach (string chunk in cc.Split(new string[] { ";" }, StringSplitOptions.RemoveEmptyEntries))
        {
            AddCC(chunk);
        }

        foreach (string chunk in bcc.Split(new string[] { ";" }, StringSplitOptions.RemoveEmptyEntries))
        {
            AddBCC(chunk);
        }
        SetSubject(subject);
        SetMessage(content);
        Send();
    }
Darj
  • 1,403
  • 1
  • 17
  • 47
  • Your second sentence is completely unclear to me. If you're talking about chaining constructors together, see http://stackoverflow.com/questions/985280/can-i-call-a-overloaded-constructor-from-another-constructor-of-the-same-class-i?rq=1 – Jon Skeet May 28 '13 at 09:40
  • This is exactly what I've wanted, thanks Jon! Sorry, lack of coffee. – Darj May 28 '13 at 09:42

2 Answers2

2

As an alternative to constructor chaining:

If you want all the constructors to initialise client and message you should move the initialisation from the default constructor to the point at which the private fields are defined, like so:

private readonly SmtpClient client = new SmtpClient(SMTPServer);
private readonly MailMessage message = new MailMessage {IsBodyHtml = true};

That way you are guaranteed that they will be initialised by any constructor that you happen to write. I think you can probably make them readonly too.

NOTE: That'll only work if SMTPServer is initialised at construction time, for example if it is a property which returns a value which doesn't depend on other fields. Otherwise you might need to use another field for it which is declared and initialised simultaneously like the two other fields.

Fields like that are initialised in the order in which they appear in the class definition (which is obviously quite important to know).

Matthew Watson
  • 104,400
  • 10
  • 158
  • 276
1

You can use the following syntax to call another constructor, it's a .Net feature:

private MyMailer() // objects initializer
{
    client = new SmtpClient(SMTPServer);
    message = new MailMessage {IsBodyHtml = true};
}

private MyMailer(string from) //from setter
    : this() // calls MyMailer()
{
    SetFrom(from);
}

public MyMailer(string from, string to, string cc, string bcc, string subject, string content)
    : this(from) // calls MyMailer(from)
{
    foreach (string chunk in to.Split(new string[] {";"}, StringSplitOptions.RemoveEmptyEntries))
    {
        AddTo(chunk);    
    }

    foreach (string chunk in cc.Split(new string[] { ";" }, StringSplitOptions.RemoveEmptyEntries))
    {
        AddCC(chunk);
    }

    foreach (string chunk in bcc.Split(new string[] { ";" }, StringSplitOptions.RemoveEmptyEntries))
    {
        AddBCC(chunk);
    }
    SetSubject(subject);
    SetMessage(content);
    Send();
}
Sean Airey
  • 6,352
  • 1
  • 20
  • 38