Reputation: 6842
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;
}
}
Upvotes: 1
Views: 235
Reputation: 1062770
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)
Upvotes: 1