这个委托使用是好还是坏?

时间:2009-10-15 14:23:23

标签: c# templates delegates

这个问题正在被问到,因为我之前没有代表最佳实践的经验

我在html中有一个无序列表,其中整个网站的结构是相同的,但列表的内容可能不同。

示例:
对象列表A

<ul>
  <li>
    <ul>
      <li>A.someMember1</li>
      <li>A.someMember2</li>
      <li>A.someMember3</li>
    </ul>
  </li>
</ul>

对象B列表

<ul>
  <li>
    <ul>
      <li>B.someMember1</li>
      <li>B.someMember2</li>
      <li>B.someMember3</li>
      <li>B.someMember4</li>
    </ul>
  </li>
</ul>

我创建了两个代表:

protected delegate void RenderHtmlMethod(HtmlTextWriter writer);
protected delegate void RenderHtmlMethodWithObjects(HtmlTextWriter writer, object obj);

以及以下方法

    private void RenderList(HtmlTextWriter writer, string title, RenderHtmlMethod headingDelegate,
        RenderHtmlMethodWithObjects itemsDelegate, object objToRender)
    {

            writer.RenderBeginTag(HtmlTextWriterTag.Fieldset);

            writer.RenderBeginTag(HtmlTextWriterTag.Legend);
            writer.HtmlEncode(title);
            writer.RenderEndTag();//end Legend

            writer.AddAttribute(HtmlTextWriterAttribute.Class, "resultList");
            writer.RenderBeginTag(HtmlTextWriterTag.Ul);
            {
                headingDelegate(writer);

                itemsDelegate(writer, objToRender);
            }
            writer.RenderEndTag();//ul

            writer.RenderEndTag(); //fieldset

    }

这样,我可以制作渲染标题的方法(只是另一个带有嵌入式ul的li),然后为每个对象列表渲染必要的列表项。

我无法重新定义我的类来实现任何接口,但是,我可以为类创建一个包装器并在那里实现render方法。你怎么看待这个?

我的结构有意义吗?还是我疯了?

3 个答案:

答案 0 :(得分:4)

我认为这不是一个糟糕的决定。但是,我认为最好是创建用于生成列表的特殊接口(或抽象类)。

public abstract class ListRenderer
{
  public abstract IEnumerable Items {get;}
  public abstract String GenerateHeaderText();
  public String GenerateItemText(objectItem);
  public abstract void RenderList(TextWriter writer);
}

然后,您只需在具体项目周围创建包装器,并将此对象传递给您的generator方法。如果您的列表以通用方式构建,则可以在ListRenderer中实现所有逻辑,然后仅覆盖GenerateHeaderText和GenerateItemText

答案 1 :(得分:0)

为什么要传递代理来执行渲染?你想让每个列表略有不同吗?如果您正在寻找一致性,我只需传递您想要呈现的对象列表以及一些标题文本,并将其全部呈现在您的方法中。例如,我提出的方法签名可能类似于:

private void RenderList<T>(HtmlTextWriter writer, string title, string headerText, List<T> objectsToRender) where T : IRender

话虽如此,如果每个名单都应该以独特的方式呈现,那么我认为你不会比我头脑中的声音更疯狂。

更新

我想我需要扩展我的代码示例......

private void RenderList<T>(HtmlTextWriter writer, string title, string headerText, List<T> objectsToRender) where T : IRender
{
    writer.RenderBeginTag(HtmlTextWriterTag.Fieldset);

    writer.RenderBeginTag(HtmlTextWriterTag.Legend);
    writer.HtmlEncode(title);
    writer.RenderEndTag();//end Legend

    writer.AddAttribute(HtmlTextWriterAttribute.Class, "resultList");
    writer.RenderBeginTag(HtmlTextWriterTag.Ul);
    {
        writer.RenderBeginTag(HtmlTextWriterTag.Div); //begin Header
        writer.AddAttribute(HtmlTextWriterAttribute.Class, "header");
        writer.HtmlEncode(headerText);
        writer.RenderEndTag(); //end Header

        // render all objects
        foreach (T obj in objectsToRender)
        {
            writer.RenderBeginTag(HtmlTextWriterTag.Li); // begin Custom Object Rendering
            obj.CustomRender(writer);
            writer.RenderEndTag(); // end Custom Object Rendering
        }
    }
    writer.RenderEndTag();//ul

    writer.RenderEndTag(); //fieldset
}

// IRender interface
public interface IRender
{
    void CustomRender(HtmlTextWriter writer);
}

答案 2 :(得分:0)

我会选择通用方法Render(HtmlTextWriter)并将所有其他参数定义为类的属性:

interface IRenderable
{
    void Render(HtmlTextWriter writer);
}

class ListComponent : IRenderable
{
    public List<IRenderable> Items { get; set; }
    public string Title { get; set; }

    public void Render(HtmlTextWriter writer)
    {
        writer.RenderBeginTag(HtmlTextWriterTag.Fieldset);

        writer.RenderBeginTag(HtmlTextWriterTag.Legend);
        writer.HtmlEncode(Title);
        writer.RenderEndTag();//end Legend

        writer.AddAttribute(HtmlTextWriterAttribute.Class, "resultList");
        writer.RenderBeginTag(HtmlTextWriterTag.Ul);

        foreach (var item in Items)
        {
            writer.RenderBeginTag(HtmlTextWriterTag.Li);
            item.Render(writer);
            writer.RenderEndTag();//li
        }

        writer.RenderEndTag();//ul

        writer.RenderEndTag(); //fieldset
    }
}