简体   繁体   中英

Force class derived from abstract class to implement constructor

I have a custom exception which looks like the following:

public abstract class MyException : Exception
{
    public MyException()
    {
    }

    public MyException(string message) : base(message)
    {
    }

    public MyException(string message, Exception inner) : base(message, inner)
    {

    }

    public abstract HttpStatusCode GetHttpStatusCode();
}

And a derived class:

public class ForbiddenException : MyException
{
    public override HttpStatusCode GetHttpStatusCode()
    {
        return HttpStatusCode.Forbidden;
    }
}

I want the derived classes to either use, or be forced to implement, the constructor formats in the abstract class.

Currently using the above, when I try to create a ForbiddenException , I get the following error:

throw new ForbiddenException("Request forbidden");

ForbiddenException does not contain a constructor that takes 1 arguments

I could manually put the constructors into each derived class of MyException but this is error prone + repeating myself.

Any advice would be appreciated.

If you want to avoid copying & pasting/errors when re-writing, consider using a Text Template. I've placed this in a .tt template in my toy class library, which I also copied your MyException into:

<#@ template debug="false" hostspecific="false" language="C#" #>
<#@ assembly name="System.Core" #>
<#@ import namespace="System.Linq" #>
<#@ import namespace="System.Text" #>
<#@ import namespace="System.Collections.Generic" #>
<#@ output extension=".cs" #>
using System;

namespace ClassLibrary2
{

<# StandardConstructors("public","ForbiddenException","MyException"); #>

}
<#+
  public void StandardConstructors(string modifiers,
       string derivedException, string baseException)
    {
        Write(modifiers);
        Write(" partial class ");
        Write(derivedException);
        Write(":");
        WriteLine(baseException);
        WriteLine("{");

        Write("\tpublic ");
        Write(derivedException);
        WriteLine("() {}");

        Write("\tpublic ");
        Write(derivedException);
        WriteLine("(string message):base(message)");
        WriteLine("\t{}");

        Write("\tpublic ");
        Write(derivedException);
        WriteLine("(string message, Exception inner):base(message,inner)");
        WriteLine("\t{}");

        WriteLine("}");
    }
#>

The only error I immediately get is I've not implemented GetHttpStatusCode but I'd expect you to be writing that in a separate file that also defines the same partial ForbiddenException class. Each new derived exception just needs you to add another StandardConstructors line to the template file. Far less error prone.

Of course, you can make this as fancy as you like, I just wrote this from scratch in a few minutes 1 .

This is one the above template produces:

using System;

namespace ClassLibrary2
{

public partial class ForbiddenException:MyException
{
    public ForbiddenException() {}
    public ForbiddenException(string message):base(message)
    {}
    public ForbiddenException(string message, Exception inner):base(message,inner)
    {}
}

}

Not pretty but it doesn't have to be - it's generated code.


1 Eg if the tabs/spacing really irks you, but also if eg you want to have more control over modifiers, etc.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM