1

I had no idea how to phrase a good title here.

I'm basically trying to use the open-closed principle, so I don't need to specify precisely which component to render, but just use an interface/abstract class instead.

I'm making a node editor. I have a List of NodeModelBases, to hold the data for each node, and for each of these, I want to insert a corresponding NodeComponent to be rendered. Currently:

<div class="diagram-html-layer">
            @foreach (NodeModelBase node in nodeModelManager.Nodes) {
                <NodeBase NodeModel="@node" OnDeleteEvent="OnDeleteNode"/>
            }
</div>

The idea is that NodeModelBase is inherited by specific types of Nodes, so I could have a "StartNode : NodeModelBase", "DelayNode : NodeModelBase" , etc., i.e. sub-classes of NodeModelBase. I may potentially have 20 or more sub-classes, and I would like to not update the above for-loop for each new added node type.

I then want to render their respective component. Currently, I have a Blazor component called NodeBase, which I just insert, because I only have one node type so far. But I would like to be able to do something like: node.GetHTML() and insert this instead.

I could have a long if-else to check which sub-class of NodeModelBase I have, and then insert the correct component, something like:

if(node is StartNode) {
    <StartNode/>
} else if (node is DelayNode) {
    <DelayNode/>
} else ...

But that's pretty inconvenient.

I know this can be done programmatically by using the RenderTreeBuilder, and making calls like builder.OpenElement(...), or builder.AddAttribute(...), so the result would look something like:

<div class="diagram-html-layer">
            @foreach (NodeModelBase node in nodeModelManager.Nodes) {
                @node.GetRenderFragment();
            }
</div>

But being a html/blazor novice, I would much prefer to be able to define the html/razor syntax normally, and somehow return/insert that.

So, any suggestions on how to be flexible about which component is inserted?

4

0 回答 0