I created a class InputBox that only has one method, which is static:
Public static Show(string i_Prompt)
this method creates an InputBoxForm and gives the form a method for this property: public Predicate<char> isKeyValid { get; set; }
which runs in here:
private void textBoxInput_KeyPress(object sender, KeyPressEventArgs e)
{
if (isKeyValid != null)
{
e.Handled = !isKeyValid(e.KeyChar);
}
}
the idea is that a developer will derive my class and create he's own logic on how to deal with getting characters from the user.
this implementation of the static Show method is:
public static string Show(string i_Prompt)
{
string input = string.Empty;
using (InputBoxForm form = new InputBoxForm(i_Prompt))
{
form.isKeyValid = s_Instance.keyValidationLogic;
if (form.ShowDialog() == DialogResult.OK)
{
input = form.Input;
}
}
return input;
}
the template is keyValidationLogic. (which return true for all the keys in the base InputBox)
the problem, as you can see that i cannot overwrite a static method.
how would I implement a template method in a static method?
I have to create an instance of the Input Box, but I want to use the derived class instance
the class InputBox is not static. i want it to be derived, so developers will be able to customize the logic of the input box.
thanks
I'm not sure your approach is the best way to to about this, but you should be able to solve your issue in the following way.
You can do this with ordinary inheritance:
class InputBox
{
protected virtual bool ValidateKey(char key)
{
// Allow anything
return true;
}
public string Show(string i_Prompt)
{
using (InputBoxForm form = new InputBoxForm(i_Prompt))
{
form.isKeyValid = this.ValidateKey;
if (form.ShowDialog() == DialogResult.OK)
{
return form.Input;
}
}
return string.Empty;
}
}
class DigitInputBox : InputBox
{
protected override bool ValidateKey(char key)
{
return key >= '0' && key <= '9';
}
}
To use:
(new MyCustomizedInputBox()).Show("Numbers only, please!");
Related
So I have a class Doorcontrol that can have 4 states
public enum DoorControlState
{
DoorClosed,
DoorOpening,
DoorOpen,
DoorBreached
}
To open the door an accescode is needed, the code is then validated and if it's correct the door is opened. If the door is not in the Closed state nothing should happen. It should go like this RequestEntry(id)[Doorcontrol]->ValidateEntryRequest(id)[IUserValidation]->OK[Doorcontrol]->Open[IDoor]->change state to DoorOpening. Idoor then calls DoorOpen and the state changes to DoorOpen and so on.
I have implemented the DoorControl class as follows
public class DoorControl
{
private IDoor _door;
private IEntryNotification _entryNotification;
private IUserValidation _userValidation;
private DoorControlState _doorControlState;
private int _id;
public DoorControl(IDoor door, IEntryNotification entryNotification, IUserValidation userValidation, DoorControlState doorControlState)
{
_door = door;
_entryNotification = entryNotification;
_userValidation = userValidation;
_doorControlState = doorControlState;
}
public void Run()
{
switch (_doorControlState)
{
case DoorControlState.DoorClosed:
bool foo = RequestEntryId();
if (foo)
{
_door.Open();
_doorControlState = DoorControlState.DoorOpening;
}
break;
case DoorControlState.DoorOpening:
_door.Close();
_doorControlState = DoorControlState.DoorOpen;
break;
case DoorControlState.DoorOpen:
// Do stuff....
break;
case DoorControlState.DoorBreached:
// Do stuff
break;
default:
throw new InvalidEnumArgumentException();
}
}
private bool RequestEntryId()
{
bool maybeFoo = _userValidation.ValidateEnetryRequest();
if (maybeFoo = true)
{
return true;
}
return false;
}
public void DoorOpened()
{
//
}
public void DoorClosed()
{
//
}
}
}
The UserValidation and Door classes are implemented as Interfaces
public interface IUserValidation
{
bool ValidateEnetryRequest();
}
public interface IDoor
{
void Open();
void Close();
}
I am testing my code using Nunit and NSubstitute
namespace DoorControl.Unit.Test
{
[TestFixture]
public class DoorControlUnitTest
{
private DoorControl _uut;
private IDoor _door;
private IEntryNotification _entryNotification;
private IUserValidation _userValidation;
private DoorControlState _doorControlState;
[SetUp]
public void SetUp()
{
_door = Substitute.For<IDoor>();
_entryNotification = Substitute.For<IEntryNotification>();
_userValidation = Substitute.For<IUserValidation>();
_doorControlState = DoorControlState.DoorClosed;
_uut = new DoorControl(_door, _entryNotification, _userValidation, _doorControlState);
}
[Test]
public void InputCorrectId()
{
_userValidation.ValidateEnetryRequest().Returns(true);
_uut.RequestEntryId(); // Can't called that cause it's private
_door.Received().Open();
}
}
}
I can't figure out how to make it call RequestEntryId only when it's in the Doorclosed state and ignore it if it's in another state.
Edit: What state the Doorcontrol is in should be hidden from everybody else.
public void InputCorrectId()
{
_userValidation.ValidateEnetryRequest().Returns(true);
if(_doorControlState == DoorControlState.DoorClosed){
_uut.RequestEntryId(); // Make it public
}
_door.Received().Open();
}
Or into the doorcontrol class like:
case DoorControlState.DoorClosed:
RequestEntryId();
I'm not sure exactly what you're asking: when you say "I can't figure out how to make it call RequestEntryId only when it's in the Doorclosed state and ignore it if it's in another state." do you mean the unit test? I can't figure out why you would want to do that. Please provide more info and I'll update this answer if I can help.
I did notice a couple of things that might help you though. First RequestEntryId has a problem:
private bool RequestEntryId()
{
bool maybeFoo = _userValidation.ValidateEnetryRequest();
if (maybeFoo = true)
{
return true;
}
return false;
}
Here maybeFoo = true is an assignment which overwrites the result of ValidateEntryRequest(). I think you intended a comparison with ==, but the whole method can be simplified to:
private bool RequestEntryId()
{
return _userValidation.ValidateEnetryRequest();
}
With that fixed we can run a few tests to check how the public Run method behaves. Given your SetUp creates a doorcontrol already in a Closed state, we can test that the door opens for valid users, and doesn't open for invalid users.
[Test]
public void ClosedDoorOpensWhenUserIsValid()
{
_userValidation.ValidateEnetryRequest().Returns(true);
_uut.Run();
_door.Received().Open();
}
[Test]
public void ClosedDoorDoesNotOpenWhenUserInvalid()
{
_userValidation.ValidateEnetryRequest().Returns(false);
_uut.Run();
_door.DidNotReceive().Open();
}
We can also check the validation is not repeated for an already opened door:
[Test]
public void OpenDoorDoesNotRevalidate()
{
_userValidation.ValidateEnetryRequest().Returns(true);
_uut.Run();
_userValidation.ClearReceivedCalls();
_uut.Run();
_userValidation.DidNotReceive().ValidateEnetryRequest();
}
Hope this gives you some ideas for testing this.
I have a form that has a button to get a method executed in another class.
Code on the form:
public delegate void CustomPreviewCreate();
public static event CustomPreviewCreate CustomPreviewCreate_Do;
private void CreatePreview()
{
if (CustomPreviewCreate_Do !=null)
{
CustomPreviewCreate_Do();
}
}
This event then gets handled in another class. What I would like to achieve is that I can feed back to the form some form of return value if the method correctly executed.
What I tried so far does not get me the result.
Here is the code:
public void Initialize()
{
SubAsstViewPartControl.CustomPreviewCreate_Do += SubAsstViewPartControl_CustomPreviewCreate_Do;
// this gives me a the compiler error that the return type is wrong
}
private bool SubAsstViewPartControl_CustomPreviewCreate_Do()
{
// do stuff
return false;
}
Is there any direct way to return value from an event handler or I need to use a separate static field to store the event result in?
Update:
Per #Jon's comment, which seemed the simplest to me, I added an answer below demonstrating the simplest approach.
The common approach is to encapsulate your value in the type of EventArgs your event expects. For example, the Framework's CancelEventArgs contains a settable bool Cancel property, allowing each CancelEventHandler to assign a value. The sender can then read the property after the event has been invoked. You could also use a container-like EventArgs class if you want to collect separate values from individual event handlers. For example:
using System;
using System.Collections.Generic;
namespace ConsoleApplication1
{
public class SingleValueEventArgs : EventArgs
{
public int Value { get; set; }
}
public class MultiValueEventArgs : EventArgs
{
private List<int> _values = new List<int>(); // Private to prevent handlers from messing with each others' values
public IEnumerable<int> Values
{
get { return _values; }
}
public void AddValue(int value) { _values.Add(value); }
}
public class Exposer
{
public event EventHandler<SingleValueEventArgs> WantSingleValue;
public event EventHandler<MultiValueEventArgs> WantMultipleValues;
public void Run()
{
if (WantSingleValue != null)
{
var args = new SingleValueEventArgs();
WantSingleValue(this, args);
Console.WriteLine("Last handler produced " + args.Value.ToString());
}
if (WantMultipleValues != null)
{
var args = new MultiValueEventArgs();
WantMultipleValues(this, args);
foreach (var value in args.Values)
{
Console.WriteLine("A handler produced " + value.ToString());
}
}
}
}
public class Handler
{
private int _value;
public Handler(Exposer exposer, int value)
{
_value = value;
exposer.WantSingleValue += exposer_WantSingleValue;
exposer.WantMultipleValues += exposer_WantMultipleValues;
}
void exposer_WantSingleValue(object sender, SingleValueEventArgs e)
{
Console.WriteLine("Handler assigning " + _value.ToString());
e.Value = _value;
}
void exposer_WantMultipleValues(object sender, MultiValueEventArgs e)
{
Console.WriteLine("Handler adding " + _value.ToString());
e.AddValue(_value);
}
}
class Program
{
static void Main(string[] args)
{
var exposer = new Exposer();
for (var i = 0; i < 5; i++)
{
new Handler(exposer, i);
}
exposer.Run();
}
}
}
Per Jon Skeet's comment, which seemed the simplest to me, the simplest approach seems to be as follows:
public delegate bool CustomPreviewCreate(); // here we declare a return type
public static event CustomPreviewCreate CustomPreviewCreate_Do;
private void CreatePreview()
{
if (CustomPreviewCreate_Do !=null)
{
bool returnval = CustomPreviewCreate_Do();
}
}
And then:
// the method is declared to return the same type
bool SubAsstViewPartControl_CustomPreviewCreate_Do()
{
// do stuff
return true; // return the value of the type declared
}
Is there a way to prevent a method from execution if it is in design time or the method can only be executed at runtime.
I got this problem while creating a custom control because there is a method call in the constructor that will only work at runtime.
now at design time while designing the form and use that control, then the form will generate the error.
now i tried this at the constructor of the user control
public ctrl_information()
{
InitializeComponent();
if (LicenseManager.UsageMode == LicenseUsageMode.Designtime)) return;
SomeMethod();
//Other code
}
what i want to achieve now is something like this.
[ExecuteOnlyAtRuntime]
public void SomeMethod()
{
//Code here
}
Then call it like this.
public ctrl_information()
{
InitializeComponent();
//if (LicenseManager.UsageMode == LicenseUsageMode.Designtime)) return; -- removing this line
SomeMethod();
}
Is it possible?
Please shed some light on this.
Thank you
Assuming that someMethod is in a control, you may use Component.DesignMode.
So a simple approach could be
public void SomeMethod()
{
if (this.DesignMode == false)
{
//Code here
}
}
Incase the Some function is not in a control, you may implement something like this -
public void SomeFunciton()
{
if(VisualStudioUtility.IsRunningInVisualStudio == false)
{
}
}
static class VisualStudioUtility
{
private const string IDE_EXE = "devenv.exe";
public static bool IsRunningInVisualStudio
{
get
{
return Environment.CommandLine.Contains(IDE_EXE);
}
}
}
This is my code:
namespace Cinemaseats
{public partial class MainForm : Form
{
private const int numOfSeats = 60;
private int numOfReservedSeats = 0;
Seat currentSeat = new Seat();
public MainForm()
{
InitializeComponent();
InitializeGUI();
}
private void InitializeGUI()
{
radioButton1.Checked = true;
namn.Text = string.Empty;
pris.Text = string.Empty;
}
private void button1_Click(object sender, EventArgs e)
{
**int seatNr = ReadAndValidateSeatNr();**
if (seatNr < 0)
{
MessageBox.Show("Välj ett föremål från listan");
return;
}
if (radioButton2.Checked)
ReserveSeat(seatNr);
else
CancelSeat(seatNr);
UpdateGUI(seatNr);
}
public int GetnumOfSeats()
{
return numOfSeats;
}
**public int ReadAndValidateSeatNr()
{
thelist.Items.Add(test); //test
return;
}
string test = Convert.ToString(2);
}**
}
I have converted my string "test" to an int but still VS says that the return value has to be an int? I want to display 60 "seats in my listbox, that is to say "Seat 1","Seat 2" and so on. I wrote a test string to see if I could make it work.I'm not sure how getter and setters methods work but I have figured otu that I would need them here?
In your ReadAndValidateSeatNr() function you are not returning anything:
public int ReadAndValidateSeatNr()
{
thelist.Items.Add(test); //test
return; //<--------- here nothing is being returned
}
My compiler gives the same error to me :P
Change return to void if you do not need to return anything:
public void ReadAndValidateSeatNr()
{
thelist.Items.Add(test); //test
//return; redundant statement - not even required in this case
}
If your requirement is something like 1 for "Seat 1", etc - go for an enum:
enum my_enum{ Seat1=1, Seat2= 2};
public int ReadAndValidateSeatNr()
{
switch(test)
{
case "Seat 1":
thelist.Items.Add(test); //test
return (int)my_enum.Seat1;
case "Seat 2":
thelist.Items.Add(test); //test
return (int)my_enum.Seat2;
}
}
If you don't want to return something in the ReadAndValidateSeatNr method you should change it like this:
public void ReadAndValidateSeatNr()
{
thelist.Items.Add(test);
}
A method can either return an int or a string (to say only one type). As other have suggested either change the return type to void if you do not want to return any thing.
If your problem is only having "Seat" string at the beginning, then you should not add the item to list box inside the method. Instead return an int from the method and add the item to your list box by doing something like this from the main block.
thelist.Items.Add("Seat " + ReadAndValidateSeatNr().ToString());
In this case your method will be retuning an int and can be used independently and you will still be able to add to your list box in the format you want it.
I'm trying to programmatically call a function with event.
How to convert string to a event in general? My problem is actually not knowing How to do this?
How to convert str to event?
str = "test1";
// UserControlsBackgroundEventArgs = EventArgs
EventArgs arg = (EventArgs)str; --> ?
UserControlsBackgroundOutput(str);
//function
private string CLICKNAME = "test0";
private void UserControlsBackgroundOutput(EventArgs e)
{
if (CLICKNAME == e.output)
return;
if (e.output == "test1"){}
}
Error solved:
I had to do
UserControlsBackgroundEventArgs arg = new UserControlsBackgroundEventArgs(CLICKNAME);
instead of
UserControlsBackgroundEventArgs arg = new (UserControlsBackgroundEventArgs)(CLICKNAME);
i've written a code that mimic you code, hopefully you will find it useful:
public class UserControlsBackgroundEventArgs
{
public string output;
public UserControlsBackgroundEventArgs(string up)
{
output = up;
}
}
public delegate void UserControlsBackgroundOutputHandle(UserControlsBackgroundEventArgs e);
public class testEvent
{
public event UserControlsBackgroundOutputHandle UserControlsBackgroundOutput;
public void DoSomeThings()
{
// do some things
if (UserControlsBackgroundOutput != null)
{
string str = "test1";
UserControlsBackgroundEventArgs arg = new UserControlsBackgroundEventArgs(str);
UserControlsBackgroundOutput(arg); // you've done that with str, whitch makes me
// you don't know what the event param is
}
}
}
public class test
{
private testEvent myTest;
private const string CLICKNAME = "whatever"; // i don't know what you want here
public test()
{
myTest = new testEvent();
myTest.UserControlsBackgroundOutput += UserControlsBackgroundOutput;
}
void UserControlsBackgroundOutput(UserControlsBackgroundEventArgs e)
{
if (CLICKNAME == e.output)
return;
if (e.output == "test1")
{
}
}
}
Your event class needs to have a constructor accepting a string. Then you will be able to create a new event instance using a string. You can't "convert" a string to an instance of the event class. If the event class comes from a library or sth and doesn't have a string constructor, you can subclass it, implement a string constructor and override the output property.
If you want this kind of conversion to be possible, you have to use an explicit operator:
public static explicit operator UserControlsBackgroundEventArgs(string s)
{
var args = new UserControlsBackgroundEventArgs();
args.output = s;
return args;
}
This is only possible with a new class, not with EventArgs, because you can't change the code of that class.
Your UserControlsBackgroundEventArgs Implementation could provide implicit/explicit casts.
Take a look at implicit keyword documentation
However, the answer from Wojciech Budniak is better.