为什么我必须在 vb.net 中为接口实现一个显然不需要在 C# 中实现的函数
本文关键字:实现 一个 不需要 函数 net vb 为什么 接口 | 更新日期: 2023-09-27 18:35:42
我正在努力将这篇代码项目中的代码从 C# 转换为 VB.net。 大部分进展顺利,但最后一点让我感到困惑,我希望有人能解释为什么。它的核心是转换一些实现接口的代码。
这是 c# 接口
namespace ViewModels
{
public interface ICustomerController : IController
{
/// <summary>
/// Return a collection of Customer information to be displayed in a list
/// </summary>
/// <returns>A collection of Customers</returns>
CustomerSelectionViewData GetCustomerSelectionViewData(string stateFilter);
/// <summary>
/// Do whatever needs to be done when a Customer is selected (i.e. edit it)
/// </summary>
/// <param name="customerId"></param>
void CustomerSelectedForEdit(CustomerListItemViewData data, BaseViewModel daddy);
/// <summary>
/// Edit this customer Id
/// </summary>
/// <param name="customerId"></param>
void EditCustomer(int customerId, BaseViewModel daddy);
/// <summary>
/// Update Customer data in the repository
/// </summary>
/// <param name="data"></param>
void UpdateCustomer(CustomerEditViewData data);
}
}
后跟实现它的文件。
using ViewModels;
using Views;
namespace Controllers
{
public partial class CustomerController : ICustomerController
{
/// <summary>
/// The ShowView methods are private. A ViewModel may request some action to take place,
/// but the Controller will decide whether this action will result in some view being
/// shown.
/// e.g. clicking a 'Search' button on a form may result in a Command being sent from the
/// View (via binding) to the ViewModel; the Command handler then asks the Controller to
/// Search for whatever.
/// The controller may (for example) use a service to return a collection of objects. if there
/// is only a single object, then it may return a single object rather than popping up a search
/// view only to have the User be presented with a single action from which to select.
/// </summary>
#region Show Views
private void ShowViewCustomerSelection()
{
CustomerSelectionView v = GetCustomerSelectionView();
v.ShowInWindow(false, "MVVM# Customer Selection");
}
#endregion
#region Get Views
private CustomerSelectionView GetCustomerSelectionView(BaseViewModel daddy = null)
{
CustomerSelectionView v = new CustomerSelectionView();
CustomerSelectionViewModel vm = new CustomerSelectionViewModel(this, v);
if (daddy != null)
{
daddy.ChildViewModels.Add(vm);
}
return v;
}
private BaseView GetCustomerEditView(int customerId, BaseViewModel daddy)
{
CustomerEditView v = new CustomerEditView();
CustomerEditViewModel vm = new CustomerEditViewModel(this, v);
vm.ViewData = GetCustomerEditViewData(customerId);
if (daddy != null)
{
daddy.ChildViewModels.Add(vm);
}
return v;
}
#endregion
}
}
和
using System.Collections.ObjectModel;
using Messengers;
using Model;
using Service;
using ViewModels;
namespace Controllers
{
public partial class CustomerController
{
/// <summary>
/// Get a collection of Customers and return an Observable collection of CustomerListItemViewData
/// for display in a list.
/// You could bypass this conversion if you wanted to present a list of Customers by binding directly to
/// the Customer object.
/// </summary>
/// <returns></returns>
public CustomerSelectionViewData GetCustomerSelectionViewData(string stateFilter)
{
CustomerSelectionViewData vd = new CustomerSelectionViewData();
vd.Customers = new ObservableCollection<CustomerListItemViewData>();
foreach (var customer in CustomerService.GetListOfCustomers(stateFilter))
{
vd.Customers.Add(new CustomerListItemViewData()
{
CustomerId = (int)customer.Id,
CustomerName = customer.Name,
State = customer.State
});
}
return vd;
}
/// <summary>
/// Get the Edit View Data for the Customer Id specified
/// </summary>
/// <param name="customerId"></param>
/// <returns></returns>
public CustomerEditViewData GetCustomerEditViewData(int customerId)
{
var customer = CustomerService.GetCustomer(customerId);
return new CustomerEditViewData()
{
CustomerId = customer.Id,
Name = customer.Name,
Address = customer.Address,
Suburb = customer.Suburb,
PostCode = customer.PostCode,
State = customer.State,
Phone = customer.Phone,
Email = customer.Email
};
}
public void UpdateCustomer(CustomerEditViewData data)
{
Customer item = new Customer()
{
Id = data.CustomerId,
Address = data.Address,
Name = data.Name,
Suburb = data.Suburb,
PostCode = data.PostCode,
Email = data.Email,
Phone = data.Phone,
State = data.State
};
CustomerService.UpdateCustomer(item);
Messenger.NotifyColleagues(MessageTypes.MSG_CUSTOMER_SAVED, data);
}
}
}
和
using Messengers;
using Service;
using ViewModels;
using Views;
namespace Controllers
{
/// <summary>
/// The controller 'is' the application.
/// Everything is controlled by this :
/// it instantiates Views and ViewModels
/// it retrieves and stores customers via services
///
/// But it does all this only in response to requests
/// made by the ViewModels.
///
/// e.g. a ViewModel may request a list of customers
/// e.g. a ViewModel may want to save changes to a customer
///
/// set up as a partial class for convenience
/// </summary>
public partial class CustomerController : BaseController, ICustomerController
{
private static ICustomerService CustomerService;
#region Constructors
/// <summary>
/// Private constructor - we must pass a service to the constructor
/// </summary>
private CustomerController()
{
}
/// <summary>
/// The controller needs a reference to the service layer to enable it to make service calls
/// </summary>
/// <param name="customerService"></param>
public CustomerController(ICustomerService customerService)
{
CustomerService = customerService;
}
#endregion
#region Public Methods
/// <summary>
/// Main entry point of the Controller.
/// Called once (from App.xaml.cs) this will initialise the application
/// </summary>
public void Start()
{
ShowViewCustomerSelection();
}
/// <summary>
/// Edit the customer with the Id passed
/// </summary>
/// <param name="customerId">Id of the customer to be edited</param>
/// <param name="daddy">The 'parent' ViewModel who will own the ViewModel that controls the Customer Edit</param>
public void EditCustomer(int customerId, BaseViewModel daddy = null)
{
BaseView view = GetCustomerEditView(customerId, daddy);
view.ShowInWindow(true, "Edit Customer");
}
/// <summary>
/// A Customer has been selected to be edited
/// </summary>
/// <param name="data">The CustomerListItemViewData of the selected customer</param>
/// <param name="daddy">The parent ViewModel</param>
public void CustomerSelectedForEdit(CustomerListItemViewData data, BaseViewModel daddy = null)
{
// Check in case we get a null sent to us
if (data != null && data.CustomerId != null)
{
NotificationResult result = Messenger.NotifyColleagues(MessageTypes.MSG_CUSTOMER_SELECTED_FOR_EDIT, data);
if (result == NotificationResult.MessageNotRegistered || result == NotificationResult.MessageRegisteredNotHandled)
{
// Nothing was out there that handled our message, so we'll do it ourselves!
EditCustomer((int)data.CustomerId, daddy);
}
}
}
#endregion
}
}
这是相应的VB转换;
接口
Namespace ViewModels
Public Interface ICustomerController
Inherits IController
''' <summary>
''' Return a collection of Customer information to be displayed in a list
''' </summary>
''' <returns>A collection of Customers</returns>
Function GetCustomerSelectionViewData(ByVal stateFilter As String) As CustomerSelectionViewData
''' <summary>
''' Do whatever needs to be done when a Customer is selected (i.e. edit it)
''' </summary>
''' <param name="customerId"></param>
Sub CustomerSelectedForEdit(ByVal data As CustomerListItemViewData, ByVal daddy As BaseViewModel)
''' <summary>
''' Edit this customer Id
''' </summary>
''' <param name="customerId"></param>
Sub EditCustomer(ByVal customerId As Integer, ByVal daddy As BaseViewModel)
''' <summary>
''' Update Customer data in the repository
''' </summary>
''' <param name="data"></param>
Sub UpdateCustomer(ByVal data As CustomerEditViewData)
End Interface
End Namespace
代码文件实现接口
Imports ViewModels
Imports Views
Namespace Controllers
Partial Public Class CustomerController
Implements ICustomerController
''' <summary>
''' The ShowView methods are private. A ViewModel may request some action to take place,
''' but the Controller will decide whether this action will result in some view being
''' shown.
''' e.g. clicking a 'Search' button on a form may result in a Command being sent from the
''' View (via binding) to the ViewModel; the Command handler then asks the Controller to
''' Search for whatever.
''' The controller may (for example) use a service to return a collection of objects. if there
''' is only a single object, then it may return a single object rather than popping up a search
''' view only to have the User be presented with a single action from which to select.
''' </summary>
#Region "Show Views"
Private Sub ShowViewCustomerSelection()
Dim v As CustomerSelectionView = GetCustomerSelectionView()
v.ShowInWindow(False, "MVVM# Customer Selection")
End Sub
#End Region
#Region "Get Views"
Private Function GetCustomerSelectionView(Optional ByVal daddy As BaseViewModel = Nothing) As CustomerSelectionView
Dim v As New CustomerSelectionView()
Dim vm As New CustomerSelectionViewModel(Me, v)
If daddy IsNot Nothing Then
daddy.ChildViewModels.Add(vm)
End If
Return v
End Function
Private Function GetCustomerEditView(ByVal customerId As Integer, ByVal daddy As BaseViewModel) As BaseView
Dim v As New CustomerEditView()
Dim vm As New CustomerEditViewModel(Me, v)
vm.ViewData = GetCustomerEditViewData(customerId)
If daddy IsNot Nothing Then
daddy.ChildViewModels.Add(vm)
End If
Return v
End Function
#End Region
End Class
End Namespace
在我看来,这些看起来是非常忠实的转换,c# 代码肯定在我从代码项目下载的解决方案中编译和运行。
实现接口的 VB 文件告诉我应该实现这些功能;GetCustomerSelectionViewData, CustomerSelectedForEdit,EditCustomer 和 UpdateCustomer.
我可以看到它们在接口中,是的,我接受逻辑规定应该实现它们,但可以肯定的是,在 C# 中也是如此,但它可以完美编译并继续完美运行。
我欢迎那些比我更了解的人的想法,以及关于我应该如何处理转换方面的建议。
编辑
下面是分部类的另外两个部分,如您所见,其中实现了相关函数。
Imports System.Collections.ObjectModel
Imports Messengers
Imports Model
Imports Service
Imports ViewModels
Namespace Controllers
Partial Public Class CustomerController
''' <summary>
''' Get a collection of Customers and return an Observable collection of CustomerListItemViewData
''' for display in a list.
''' You could bypass this conversion if you wanted to present a list of Customers by binding directly to
''' the Customer object.
''' </summary>
''' <returns></returns>
Public Function GetCustomerSelectionViewData(ByVal stateFilter As String) As CustomerSelectionViewData
Dim vd As New CustomerSelectionViewData()
vd.Customers = New ObservableCollection(Of CustomerListItemViewData)()
For Each customer In CustomerService.GetListOfCustomers(stateFilter)
vd.Customers.Add(New CustomerListItemViewData() With {.CustomerId = CInt(customer.Id), .CustomerName = customer.Name, .State = customer.State})
Next customer
Return vd
End Function
''' <summary>
''' Get the Edit View Data for the Customer Id specified
''' </summary>
''' <param name="customerId"></param>
''' <returns></returns>
Public Function GetCustomerEditViewData(ByVal customerId As Integer) As CustomerEditViewData
Dim customer = CustomerService.GetCustomer(customerId)
Return New CustomerEditViewData() With {.CustomerId = customer.Id, .Name = customer.Name, .Address = customer.Address, .Suburb = customer.Suburb, .PostCode = customer.PostCode, .State = customer.State, .Phone = customer.Phone, .Email = customer.Email}
End Function
Public Sub UpdateCustomer(ByVal data As CustomerEditViewData)
Dim item As New Customer() With {.Id = data.CustomerId, .Address = data.Address, .Name = data.Name, .Suburb = data.Suburb, .PostCode = data.PostCode, .Email = data.Email, .Phone = data.Phone, .State = data.State}
CustomerService.UpdateCustomer(item)
Messenger.NotifyColleagues(MessageTypes.MSG_CUSTOMER_SAVED, data)
End Sub
End Class
End Namespace
和
Imports Messengers
Imports Service
Imports ViewModels
Imports Views
Namespace Controllers
''' <summary>
''' The controller 'is' the application.
''' Everything is controlled by this :
''' it instantiates Views and ViewModels
''' it retrieves and stores customers via services
'''
''' But it does all this only in response to requests
''' made by the ViewModels.
'''
''' e.g. a ViewModel may request a list of customers
''' e.g. a ViewModel may want to save changes to a customer
'''
''' set up as a partial class for convenience
''' </summary>
Partial Public Class CustomerController
Inherits BaseController
Implements ICustomerController
Private Shared CustomerService As ICustomerService
#Region "Constructors"
''' <summary>
''' Private constructor - we must pass a service to the constructor
''' </summary>
Private Sub New()
End Sub
''' <summary>
''' The controller needs a reference to the service layer to enable it to make service calls
''' </summary>
''' <param name="customerService"></param>
Public Sub New(ByVal customerService As ICustomerService)
CustomerController.CustomerService = customerService
End Sub
#End Region
#Region "Public Methods"
''' <summary>
''' Main entry point of the Controller.
''' Called once (from App.xaml.cs) this will initialise the application
''' </summary>
Public Sub Start()
ShowViewCustomerSelection()
End Sub
''' <summary>
''' Edit the customer with the Id passed
''' </summary>
''' <param name="customerId">Id of the customer to be edited</param>
''' <param name="daddy">The 'parent' ViewModel who will own the ViewModel that controls the Customer Edit</param>
Public Sub EditCustomer(ByVal customerId As Integer, Optional ByVal daddy As BaseViewModel = Nothing)
Dim view As BaseView = GetCustomerEditView(customerId, daddy)
view.ShowInWindow(True, "Edit Customer")
End Sub
''' <summary>
''' A Customer has been selected to be edited
''' </summary>
''' <param name="data">The CustomerListItemViewData of the selected customer</param>
''' <param name="daddy">The parent ViewModel</param>
Public Sub CustomerSelectedForEdit(ByVal data As CustomerListItemViewData, Optional ByVal daddy As BaseViewModel = Nothing)
' Check in case we get a null sent to us
If data IsNot Nothing AndAlso data.CustomerId IsNot Nothing Then
Dim result As NotificationResult = Messenger.NotifyColleagues(MessageTypes.MSG_CUSTOMER_SELECTED_FOR_EDIT, data)
If result = NotificationResult.MessageNotRegistered OrElse result = NotificationResult.MessageRegisteredNotHandled Then
' Nothing was out there that handled our message, so we'll do it ourselves!
EditCustomer(CInt(data.CustomerId), daddy)
End If
End If
End Sub
#End Region
End Class
End Namespace
CustomerController
是一个partial class
,因此方法在类的其他部分(CustomerController_DataRetrieval.cs,CustomerController_ViewManagement.cs)中实现。
看看这行代码:
public partial class CustomerController : ICustomerController
请注意 - 这是部分类。
这意味着项目中的其他地方还有此类的其他部分,并且所有ICustomerController
接口方法的实现都应在该部分中 - 并且可能不会出现在您演示的代码部分中。
在 C# 中,无法将类声明为实现某个接口,而不在类的任何部分实现该接口方法。
这绝对是不可能的。当我编译您提供的源代码时,出现四个错误。正是您所期望的四个错误:
'ViewModels.Controllers.CustomerController' 不实现接口成员 'ViewModels.ICustomerController.UpdateCustomer(ConsoleApplication8.CustomerEditViewData)' 'ViewModels.Controllers.CustomerController' 不实现接口成员 'ViewModels.ICustomerController.EditCustomer(int, ConsoleApplication8.BaseViewModel)' 'ViewModels.Controllers.CustomerController' 不实现接口成员 'ViewModels.ICustomerController.CustomerSelectedForEdit(ConsoleApplication8.CustomerListItemViewData, ConsoleApplication8.BaseViewModel)' 'ViewModels.Controllers.CustomerController' 不实现接口成员 'ViewModels.ICustomerController.GetCustomerSelectionViewData(string)'
请注意,您的类是partial
.您确定您没有在其他地方定义该方法吗?它根本无法不实施。
您缺少实现接口方法的方法上的"实现"子句。我刚刚使用适当的"实现"子句重现了下面转换的有趣部分 - 同样在 VB 中,您不能使用可选参数来实现非可选参数:
Partial Public Class CustomerController
Implements ICustomerController
Public Function GetCustomerSelectionViewData(ByVal stateFilter As String) As CustomerSelectionViewData Implements ICustomerController.GetCustomerSelectionViewData
Return Nothing
End Function
Public Sub UpdateCustomer(ByVal data As CustomerEditViewData) Implements ICustomerController.UpdateCustomer
End Sub
End Class
Partial Public Class CustomerController
Inherits BaseController
Implements ICustomerController
Public Sub EditCustomer(ByVal customerId As Integer, ByVal daddy As BaseViewModel) Implements ICustomerController.EditCustomer
End Sub
Public Sub CustomerSelectedForEdit(ByVal data As CustomerListItemViewData, ByVal daddy As BaseViewModel) Implements ICustomerController.CustomerSelectedForEdit
End Sub
End Class