如何提供部分方法作为可选操作
我正在迁移一些代码并拥有格式良好的查找表,但由于向后兼容性,它们必须转换为过时的结构才能使用。
我有一个 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 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
错误是正确的;如果未实现,部分方法不存在,因此您无法以这种方式将委托绑定到它们。这里最好的选择是基于开关(或类似的)手动调用它,或者如果您确实需要委托,请查找带有反射的方法(记住指定非公共绑定标志)并使用
Delegate.CreateDelegate
(如果该方法存在)。或者一个懒惰的选项:现在将您的委托绑定到
OnCardTypeVisit
而不是CardTypeVisit
。就委托而言,这也可以像将其更改为间接委托一样简单,这与
On*
方法非常相似:(但是,如果这是一个表达式 而不是代表我预计会失败)
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:now bind your delegate to
OnCardTypeVisit
instead ofCardTypeVisit
.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:(however, if that is an expression rather than a delegate I would expect failure)