【问题标题】:How to make these 2 blocks of almost identical code reusable?如何使这两个几乎相同的代码块可重用?
【发布时间】:2011-03-26 23:00:55
【问题描述】:

我需要关于如何使以下两个代码块可重用的建议。我必须生成另一个资金表,在此过程中,我想创建 FundsTable.ascx 部分视图,所有需要显示资金表的视图都可以使用。

// Inherits="System.Web.Mvc.ViewPage<CompanyViewModel> // this is a company
<%foreach (var fund in Model.PageFunds){%>

    <% foreach (var shareClass in fund.ShareClasses) {%>

        <tr class="shareclass">
            <td>
                // displays an image if the ViewModel's Company is not unlisted
                <%= Html.TearsheetImage((Model.Company.ListingType != ListingType.UNLISTED))%>
            </td>
        </tr>
<% } }%>

// Inherits="System.Web.Mvc.ViewPage<GroupViewModel> // this is a group of companies
<%foreach (var fund in Model.PageFunds){%>

    <% foreach (var shareClass in fund.ShareClasses) {%>

        <tr class="shareclass">
            <td>
                // displays an image if any Company in the ViewModel's 
                // List<Company> is not unlisted
                <%= Html.TearsheetImage(
                        (Model.Companies.WithCompanyId(fund.Company.Id) != ListingType.UNLISTED))%>
            </td>
        </tr>
<% } }%>

我认为我需要在某个地方抽象出这些差异,但我不确定该放在哪里。我应该在这里遵循任何经验法则吗?

CompanyViewModelGroupViewModel 是否都应该实现一个接口来决定该项目是否是未列出的?另外,我的 FundTable.ascx 应该是什么类型?我在想CompanyViewModelGroupViewModel 都可以扩展FundViewModel(或其他东西),我可以将FundTable 设为ViewUserControl&lt;FundViewModel&gt;,但我认为这不会起作用,因为需要确定是否显示图像的功能需要独立来自CompanyViewModel & GroupViewModel

另外,我想得越多,我就越自欺欺人!有什么想法或建议吗?谢谢

【问题讨论】:

    标签: c# asp.net-mvc partial-views abstraction code-reuse


    【解决方案1】:

    如果我没看错的话,代码的不同之处仅在于您确定是否显示图像。

    如果这是正确的,这里是进行一些函数式编程的理想场所!

    为您的 .ascx 创建一个视图模型。我们称之为 FundsTable。

    它将有两个属性:

    Func<PageFund,bool> ShowImage {get;set;}
    IEnumerable PageFund Funds {get;set;}
    

    使您的 FundsTable.ascx 对该对象进行强类型化。

    现在可以传入你是否显示的逻辑:

    FundsTable ft = new FundsTable();
    ft.ShowImage = f => f.SomeCombinationOfLogic == SomeOtherThing; //<-- Your function can be anything that returns a bool
    

    现在你可以这样做了:

    <% foreach (var shareClass in fund.ShareClasses) {%>
    
        <tr class="shareclass">
            <td>
                // displays an image if any Company in the ViewModel's 
                // List<Company> is not unlisted
               <% if(Model.ShowImage(fund)) {%>
                   <%= Html.TearsheetImage(fund)%>
               <% } %>
            </td>
        </tr>
    

    现在,我很难说出这些类之间是如何相互关联的,因此您可能必须改变类型和逻辑,但这样的方法应该可行。当您为表格设置视图模型时,只需传入将确定是否显示图像的函数。如果 Tearsheet 查找需要这种复杂性,请添加另一个 Func 属性。

    【讨论】:

    • 这看起来很有趣。我有点不确定如何实现它。我将不得不在 Group View 和 Company View 上有一条关于 RenderPartial 的指令,类似于:&lt;%= Html.RenderPartial("FundTable", Model) %&gt;,但这必须能够包含区分它们所需的逻辑。我该怎么做?
    • 在您执行 RenderPartial 之前,为 FundTable 创建模型并将其传入:&lt;% FundTable ft = new FundTable() {ShowImage = f=&gt; YourLogicHere, Funds = Model.PageFunds}; %&gt; &lt;%= Html.RenderPartial("FundTable", ft) %&gt;
    • 谢谢哥们,这成功了。这正是我们在这个项目中所需要的。我现在在两个地方使用 FundsTable,第三个设置明天实施。我还可以在整个解决方案中全面应用此修改。我们将把这个项目付诸实践!
    【解决方案2】:

    对我而言,此类问题的根源在于 Company viewmodel 和 Group of Companies 视图模型本质上是相同的(或应该是相同的),而您不知何故,可能无意中,设法从中制作了两个不同的 viewmodel .常见的逻辑是,一组公司应该只是一个List&lt;CompanyViewModel&gt;。您可以将列表发送到视图或视图用户控件。您不必为它发明一个新的视图模型类,只需将集合作为属性包含在该类中。

    看看你在评论的两行中写了什么并考虑一下。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2015-06-06
      • 1970-01-01
      • 2023-03-27
      • 1970-01-01
      • 2012-02-20
      • 1970-01-01
      • 1970-01-01
      • 2020-06-26
      相关资源
      最近更新 更多