0

So, I have 2 base interfaces. For example:

public interface IPageParameter
{
    int Pagenumber { get; set; }
}
public interface IPageModel
{
    int CurrentPage { get; set; }

    IPageParameter GetLinkParameter();
}

now I want to extent them, without changing them, so I write two new Interfaces:

public interface IPageParameterExt : IPageParameter
{
    int PerPage { get; set; }
}
public interface IPageModelExt : IPageModel
{
    int CurrentPerPage { get; set; }

    new IPageParameterExt GetLinkParameter();
}

now if I implement this in a class I need to write both functions out

public class DefaultPageParameterExt : IPageParameterExt
{
    public int Pagenumber { get; set; }
    public int PerPage { get; set; }
}

public class PageModel : IPageModelExt
{
    public int CurrentPage { get; set; }
    public int CurrentPerPage { get; set; }


    IPageParameterExt IPageModelExt.GetLinkParameter()
    {
        return new DefaultPageParameterExt()
        {
            Pagenumber = CurrentPage,
            PerPage = CurrentPerPage
        };
    }

    IPageParameter IPageModel.GetLinkParameter()
    {
        return ((IPageModelExt)this).GetLinkParameter();
    }
}

But that doesn't seem very good to me. I mean, if it extends further, does that mean that each time there have to be written another GetLinkParameter? Or is there a way to tell an interface that this function can be used for the function of its Parent? Or tell the class that you can use this function as well for the implementation for both functions?

EDIT: Okay, because a question here is what I want to do with the given Example (which is the simplest time I need this, but I need it in similar Terms for a few other Tasks):

I currently work with ASP Core 2.0.5 Razorpages and have implemented multiple IHtmlHelper extensions, there the Pagemodels have implement the IPageModel to be able to create some simple paging of elements. The IPageParameter contains what is needed to create a Hyperlink with changed Parameters (eg Pagenumber = 1 for first Page or Pagenumber += 1 for next Page).

Now my Job is it to create an IHtmlHelper-extension which allows it to choose how many Elements on Each Page are displayed, instead of using a fixed Value.

EDIT2:

Here some simplified code for a Extension since it was requested.

public static IHtmlContent GetPageButtons<TModel>(this IHtmlHelper<TModel> helper, TModel Model)
        where TModel : IPageModel
{
    var urlHelper = new UrlHelper(helper.ViewContext);
    var html = new HtmlContentBuilder();
    var para = Model.GetLinkParameter();

    string prevclass = Model.CurrentPage <= 1 ? "btn btn-default disabled" : "btn btn-default";

    html.AppendHtml(@"<table style=""width:1%"">")
            .AppendHtml("<tr>")
                .AppendHtml("<td>");

    /*other buttons*/

    para.Pagenumber = Model.CurrentPage -1;

    html
                    .AppendFormat(@"<a href=""{1}"" class=""{0}"">{2}</a>", prevclass, urlHelper.Action("", para), "<")
                .AppendHtml("</td>")

    /*other buttons*/

            .AppendHtml("</tr>")
        .AppendHtml("</table>");

    return html;
}
9
  • 2
    That's where generics <T> become handy but probably, in this case, the fault is in the base design. You should be able, whenever possible, to work with the returned base class/interface without knowing the exact type. Commented May 25, 2018 at 8:49
  • This is normal... You need to implement all members from the interface. Commented May 25, 2018 at 8:50
  • @AdrianoRepetti good Idea and it would work if it has been implemented like this to begin with. Commented May 25, 2018 at 9:30
  • Hiding a member of a base-class/-interface is cumbersome. In particular clients that only use your base-interface won´t call the new implementation, but allways the base-one. Commented May 25, 2018 at 9:44
  • 1
    @Yobikir definitely, however it's a tech debt that I'd address ASAP. Users of those interfaces have to know too much about their implementation and that's incredibly error-prone. You may want to post what you're trying to achieve with this design (not just how you made it), maybe there is something easy. Commented May 25, 2018 at 10:24

1 Answer 1

1

Thas a good deal for generics. Instead of writing new extensions for every possible type, simply use a single method for all possible types. Then you don´t even need any extending interface:

public interface IPageModel<T>
{
    int CurrentPage { get; set; }    
    T GetLinkParameter<T>();
}

public class PageModel : IPageModel<IMyInterface>
{
    public int CurrentPage { get; set; }

    IMyInterface GetLinkParameter()
    {
        return new DefaultPageParameterExt()
        {
            Pagenumber = CurrentPage,
            PerPage = CurrentPerPage
        };
    }
}
Sign up to request clarification or add additional context in comments.

6 Comments

if I did that I would have to change every method which already uses IPageModel(since IPageModel<IPageParameter> cannot be converted to IPageModel<IPageParameterExt>). And I can't do that. Still thanks for the answer.
Then why not make IPageModelExt-interface generic this way and let all classes implement that one?
Because I would still need to implement both IPageParameter IPageModel.GetLinkParameter() and IPageParameterExt IPageModelExt<IPageParameterExt>.GetLinkParameter(), which was what I trying to prevent.
Sure, bot only twice, not again and again for every new type.
True enough, that would help future implementations, but still doesn't help me right now. Please remember that, that up there is just an example, what I'm working on is a little bit more complex and an easier solution would have saved me a lot of time.
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.