Blazor component as partial class doesn't see implemented interface method from inside its view

481 Views Asked by At

I have a Blazor component with a separate code behind file as a partial class, not component base class. This class inherits from MyComponentBase and implements IMyInterface:

public interface IMyInterface { Task Export(); }

public partial class TableComponent<TRow, TTable> : 
    MyComponentBase<TableModel<TTable>>, IMyInterface
    where TRow : DataRow
    where TTable : TypedTableBase<TRow>
{
    public async Task Export() {}
}

I want to call the implemented method Export from the component's view. It works in the second button only (see code below) - with explicit conversion to the interface. For the first case it says that "Export" method doesn't exist in the current context:

@inherits MyComponentBase<TableModel<TTable>>
@typeparam TRow where TRow : DataRow
@typeparam TTable where TTable : TypedTableBase<TRow>
@*@implements IMyInterface*@@*throws doesn't implement IMyInterface*@

<button @onclick="@(() => Export())"/>Export</button>    
<button @onclick="@(() => ((IMyInterface)this).Export())"/>Export</button>

Why can't I just call the Export method without conversion? Something wrong with syntax in the view? I'm not sure whether I made it right - perhaps it requires additional

@implements IMyInterface

under type parameters in the view. But in this case it says that my component doesn't implement IMyInterface.

Update: added "[member name] doesn't exist in the current context" error message from the compiler when using the Export without casting to interface.

2

There are 2 best solutions below

0
Alex34758 On BEST ANSWER

Sorry guys, my explanation in the original post was not so clear, because I didn't understand my situation well. But the issue laid in such a trivial place. I just used another component from another folder structure as a base for my new component, but forgot to adjust the namespace according to the new folder structure, where I placed this my new component.

So, a little history of my investigations. As I mentioned later while trying to find the issue and simplified the component to just a single string field, even this field were not seen from the view - I received error message like "[member name] doesn't exist in the current context" - and that was very strange. Tried to relocate the whole component (razor and razor.cs files) to another folder with cut-paste within the Solution Explorer, and Visual Studio corrected the namespaces. And only after that all worked well. Then I tried to get the component back to its original location - again with the help of Visual Studio - and all worked fine again. Then I guessed that the issue lies in the namespace names, as MrC aka Shaun Curtis said in his answer. Just adjusting the namespace in my original component (with the whole, unsimplified code) removed all errors as well as in my simplified component.

It doesn't require

@implements IMyInterface

in the view. And

((IMyInterface)this).Export()

will not work, because it leads to the interface implementation, not to the implementation in my component class.

1
MrC aka Shaun Curtis On

It should all work.

The throws doesn't implement IMyInterface suggests that TableComponent.razor and TableComponent.razor,cs aren't being linked properly - maybe a namespace problem?

Here's a simplified version of your code (I think) that demonstrates interfaces working as expected.

public interface IMyComponent
{
    public void Execute();
}

MyComponent.razor

@implements IMyComponent
<h3>MyComponent</h3>

<button class="btn btn-primary" @onclick=this.Execute >Click</button>

MyComponent.razor.cs

public partial class MyComponent : ComponentBase, IMyComponent
{
    protected string? message;
    public void Execute()
    {
        message = DateTime.Now.ToLongTimeString();
    }
}

Index.razor

@page "/"
@inherits MyComponent

<PageTitle>Index</PageTitle>

<h1>Hello, world!</h1>

Welcome to your new app.

<div class="alert alert-info">@this.message</div>

Index.razor.cs

using Microsoft.AspNetCore.Components;

namespace SO75750129.Pages;

public partial class Index : MyComponent
{
}