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

发布于 2024-11-17 09:14:19 字数 3127 浏览 2 评论 0原文

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

我有一个 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>

这是一个精简的 Model

// 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 + "|";
        //}
    }
}

Base LookupTable 视图模型,它将返回 Select Item List 数据

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;
    }
}

I am migrating some code and have nicely formatted Look-up Tables but they have to be converted into archaic structures for use because of backward compatibility.

I have a GetLookupTable() method which goes and gets a list of SelectItemList, all off my models and lookup calls are code generated but I need to manually alter some of the return SelectItem's so I have implemented a Visitor Pattern that the developer can implement if they wish.

The visitor is done as a Partial Method and if developer wants to implement they can, but I'm getting an error as shown below

Error 132 Cannot create delegate from method 'InfoChoice.Web.Admin.ViewModels.Product.ProductCreditCardViewModel.LookupTableViewModel.CardTypeVisit(System.Web.Mvc.SelectListItem)' because it is a partial method without an implementing declaration

Here is the calling code using Razor

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

Here is a stripped down Model

// 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 + "|";
        //}
    }
}

Base LookupTable view model that will return Select Item List data

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;
    }
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

女皇必胜 2024-11-24 09:14:19

错误是正确的;如果未实现,部分方法不存在,因此您无法以这种方式将委托绑定到它们。这里最好的选择是基于开关(或类似的)手动调用它,或者如果您确实需要委托,请查找带有反射的方法(记住指定非公共绑定标志)并使用 Delegate.CreateDelegate (如果该方法存在)。或者一个懒惰的选项:

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

现在将您的委托绑定到 OnCardTypeVisit 而不是 CardTypeVisit

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

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

但是,如果这是一个表达式 而不是代表我预计会失败)

The error is correct; partial methods do not exist if not implemented, so you can't bind a delegate to them in quite that way. Your best option here is either to call it manually based perhaps on a switch (or similar), or if you really need a delegate, look for the method with reflection (remembering to specify non-public binding-flags) and use Delegate.CreateDelegate if the method turns out to exist. Or a lazy option:

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

now bind your delegate to OnCardTypeVisit instead of CardTypeVisit.

In terms of delegates, this could also be as simple as changing it to an indirect delegate, which is very similar to the On* approach:

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

(however, if that is an expression rather than a delegate I would expect failure)

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文