I'll struggling with a IView on a MVP project I'm developing.
The View interface is:
public interface IView : IBaseView
{
TextBox ClientId { get; set; }
TextBox ClientName { get; set; }
Button SaveClient { get; set; }
Button NextClient { get; set; }
Button PreviousClient { get; set; }
Button DiscardChanges {get;set;}
bool ReadOnly { get; set; }
ListBox MyLittleList { get; set; }
C Get<C>(string controlName) where C : Control;
}
The problem lies on the Get<C> method. The real implemenation is:
public C Get<C>(string ControlName) where C : Control
{
var controlName = ControlName.ToLower();
var underlyingControlName = controlName[0] + ControlName.Substring(1);
var underlyingControl = this.Controls.Find(underlyingControlName, true).FirstOrDefault();
return underlyingControl as C;
}
How do I mock this easily?
I've tried:
var view = Substitute.For<IView>();
view.ClientId = new System.Windows.Forms.TextBox();
view.ClientName = new System.Windows.Forms.TextBox();
view.DiscardChanges = new System.Windows.Forms.Button();
view.MyLittleList = new System.Windows.Forms.ListBox();
view.NextClient = new System.Windows.Forms.Button();
view.PreviousClient = new System.Windows.Forms.Button();
view.ReadOnly = false;
view.SaveClient = new System.Windows.Forms.Button();
view.Get<TextBox>("ClientId").Returns(view.ClientId);
view.Get<TextBox>("ClientName").Returns(view.ClientId);
view.Get<Button>("DiscardChages").Returns(view.DiscardChanges);
view.Get<ListBox>("DiscardChages").Returns(view.MyLittleList);
view.Get<Button>("NextClient").Returns(view.NextClient);
view.Get<Button>("PreviousClient").Returns(view.PreviousClient);
view.Get<Button>("SaveClient").Returns(view.SaveClient);
But when I called view.Get<Button>("DiscardChanges"), it returns null instead of the view.DiscardChanges button. What I'm doing wrong?
This is used because I do "autowiring". The presenter checks the methods he declared and checks against the View. If there's a match (like a OnNextClient method on the presenter and a NextClient Button on the view) he auto wires it.
protected void wireEventsTo(IBaseView view)
{
Type presenterType = this.GetType();
Type viewType = view.GetType();
foreach (var method in presenterType.GetMethods())
{
var methodName = method.Name;
if (methodName.StartsWith("On"))
{
var presenterMethodName = methodName.Substring(2);
var matchingMember = viewType.GetMember(nameOfMemberToMatch).FirstOrDefault();
if (matchingMember == null) return;
if (matchingMember.MemberType == MemberTypes.Property)
{
wireMember(view, matchingMember, method);
}
}
}
}
private void wireMember(IBaseView view, MemberInfo match, MethodInfo method)
{
var matchingMemberType = ((PropertyInfo)match).PropertyType;
if (matchingMemberType == typeof(Button))
{
var matchingButton = view.Get<Button>(match.Name);
var eventHandler = (EventHandler)EventHandler.CreateDelegate(typeof(EventHandler), this, method);
matchingButton.Click += eventHandler;
}
}
PS: I did try to mock the whole form but was granted the message: "DynamicProxy was unable to successfully replicate non-inheritable attribute System.Security.Permissions.UIPermissionAttribute".
Anyway, I'm almost giving up on the whole MVP. A lotta work.