如何将部分方法作为可选Action提供

时间:2011-06-28 08:17:16

标签: c# code-generation partial-methods

我正在迁移一些代码,并且具有格式良好的查找表,但由于向后兼容性,它们必须转换为古老的结构才能使用。

我有一个GetLookupTable()方法,它获取了一个SelectItemList列表,所有关闭我的模型和查找调用都是代码生成但我需要手动修改一些返回的SelectItem,所以我实现了一个开发者的访问者模式如果他们愿意,可以实施。

访问者是作为部分方法完成的,如果开发人员希望实现,可以,但我收到错误,如下所示

  

错误132无法从方法'InfoChoice.Web.Admin.ViewModels.Product.ProductCreditCardViewModel.LookupTableViewModel.CardTypeVisit(System.Web.Mvc.SelectListItem)'创建委托,因为它是没有实现声明的部分方法

以下是使用Razor的调用代码

<div class='row'>
    <label>Card Type</label>
    @Html.CheckBoxListFor(model => model.CardType, @Model.LookupTable.CardType)
    David Says: @Model.CardType
</div>

这是一个精简模型

// Generated model
public partial class ProductCreditCardViewModel
{
    [Required]
    [DisplayName("Account - Card Type")]
    [DefaultValue("")]
    public string CardType { get; set; }


    // ***************************************************************************************************
    // Lookup Table calls for this model (Generated)
    // ***************************************************************************************************
    public partial class LookupTableViewModel : BaseLookupTableViewModel
    {
        partial void CardTypeVisit(SelectListItem item);

        public SelectList CardType
        {
            get
            {
                return GetLookupItems("ProductCreditCardCardType", CardTypeVisit);
            }
        }
    }

}

public partial class ProductCreditCardViewModel
{
    // Custom Implementation Goes Here
    public partial class LookupTableViewModel : BaseLookupTableViewModel
    {
        //partial void CardTypeVisit(SelectListItem item)
        //{
        //    item.Value = "|" + item.Value + "|";
        //}
    }
}

将返回选择项目列表数据的基本查找表视图模型

public class BaseLookupTableViewModel
{
    public SelectList GetLookupItems(string lookupName)
    {
        return GetLookupItems(lookupName, "Name", "Text", null, null);
    }
    public SelectList GetLookupItems(string lookupName, Action<SelectListItem> itemVisitor)
    {
        return GetLookupItems(lookupName, "Name", "Text", null, itemVisitor);
    }
    public SelectList GetLookupItems(string lookupName, string dataValueField, string dataTextField, object selectedValue, Action<SelectListItem> itemVisitor)
    {
        // Go get some data from DataStore
        var list = App.Data.Lookup.GetLookupList(lookupName);

        // Convert to IEnumerable<SelectItemList>
        var result = new SelectList(list, dataValueField, dataTextField, selectedValue);

        // If developer would like to alter that list before it is returned, then developer should implement an item visitor
        if (itemVisitor != null)
        {
            foreach (var item in result)
            {
                itemVisitor(item);
            }
        }

        return result;
    }

    public void SampleVisitor(SelectListItem item)
    {
        item.Value = "Modified: " + item.Value;
    }
}

1 个答案:

答案 0 :(得分:1)

错误是正确的;部分方法不存在如果没有实现,那么你就不能以这种方式将委托绑定到它们。这里你最好的选择是根据交换机(或类似的)手动调用它,或者如果你 真的需要 一个委托,请查找带反射的方法(记住)如果方法证明存在,则指定非公共绑定标志)并使用Delegate.CreateDelegate。或者是一个懒惰的选择:

private void OnCardTypeVisit(SelectListItem item) { CardTypeVisit(item); }
partial void CardTypeVisit(SelectListItem item);

现在将您的代理绑定到OnCardTypeVisit而不是CardTypeVisit

就代表而言,这也可以像将其更改为间接委托一样简单,这与On*方法非常相似:

return GetLookupItems("ProductCreditCardCardType", x => CardTypeVisit(x));

(但是,如果那是表达式而不是委托我会期望失败)