Having two variables mirror each other - c#

class InputBox : TextBox
{
private object value;
protected override void OnLostFocus(EventArgs e)
{
base.OnLostFocus(e);
try
{
value = TypeDescriptor.GetConverter(value.GetType()).ConvertFromString(Text);
}
catch (Exception e1)
{
Utils.offensiveMessage("Invalid format! This field accepts only " + value.GetType().Name + "!");
Focus();
Text = value.ToString();
}
}
public InputBox(object value) : base()
{
this.value = value;
initializeComponent();
}
private void initializeComponent()
{
Text = value.ToString();
}
}
This class here takes an object as an input, represents it as a string and then makes sure that whatever is written in the textbox stays of the same type. It has it's limitation as to what types it can handle (value-types only), but I'm working within those confines. Why do I need this?
I have a large class that has a lot of subclasses that all in the end contain value-types. What I want is to present that data to the user and enable him to edit it. This is kind of an atom of my UI.
What would be great here is a way for a variable that I have in my large class to be mirrored by the variable in the above displayed class. When I change one in the little class, the one in the big class is changed in the same manner.
How can I do it?

I would look at using Winforms Databinding - it does this already with two way notification, if you support INotifyPropertyChanged on the large class.
However, if you don't want to use databinding for some reason, you can consider this as an alternative to just make your code work:
public static class Program
{
public static void Main()
{
var largeClass = new LargeClass() { Blah = 423 };
var inputBox = new InputBox<double>(
() => largeClass.Blah,
(a) => largeClass.Blah = a
);
}
}
public class LargeClass
{
public double Blah { get; set; }
}
public class InputBox<T> : TextBox
{
protected override void OnLostFocus(EventArgs e)
{
base.OnLostFocus(e);
try
{
_setter((T)TypeDescriptor.GetConverter(typeof(T)).ConvertFromString(Text));
}
catch (Exception e1)
{
//Utils.offensiveMessage("Invalid format! This field accepts only " + value.GetType().Name + "!");
Focus();
Text = _getter().ToString();
}
}
private Func<T> _getter;
private Action<T> _setter;
public InputBox(Func<T> getter, Action<T> setter) : base()
{
_getter = getter;
_setter = setter;
InitializeComponent();
}
private void InitializeComponent()
{
Text = _getter().ToString();
}
}

I ended up creating a wrapper that implemented an observer-pattern type interface.
Wrapping the object made sure that even value-types were passed as references (since I was now passing the wrapper instead of the value).
I setup the observer pattern so that the observed wrapped object could notify any observers which would then update accordingly.

Related

How to pass abstract method as reference?

I will admit, i am doing homework and i am stuck on this one question (Part A). How do i pass the notice method as reference to the railway signal ? Can't i just find out which class was called in the abstract constructor and then print the class name within the notify method? For example:
RailwayUser
private string className;
public RailwayUser()
{
Type type = this.GetType();
className = type.Name;
}
public void PrintClassName()
{
Console.Writeline(className);
}
RailwaySignal Class
public void Notify()
{
foreach(RailwayUser u in _watches)
{
u.PrintClassName();
u.Notice(State)
}
}
This kind of code / design is flawed, since what it does is RailwayUser, registers the object reference with the _watchers List in the RailWaySignal class, which in turn calls the public Notice method on each user when Notify is invoked, which is not how Event Signaling or Function Pointer works. In fact public _watchers is dangerous, as it can be cleared by any user, though that can be moderated using property access
Code with Issue
public void Notify()
{
foreach(RailwayUser u in _watches)
{
u.PrintClassName();
u.Notice(State)
}
}
Following shall be the actual code using events and delegates:
Correct Version
Code Snippet Online - https://www.jdoodle.com/embed/v0/uEc
void Main()
{
List<RailwayUser> railwayUsers = new List<RailwayUser>();
railwayUsers.Add(new RailwayUser());
railwayUsers.Add(new RailwayUser());
RailwayUser.TestNotification();
}
public enum Colour
{
Red,
Green,
NoSignal
}
public class RailwaySignal
{
public string Name {get; set;}
public RailwaySignal(string railwaySignalName)
{
Name = railwaySignalName;
}
// Delegate for handling event
public delegate void RailwaySignalEventHandler(object source, Colour e);
// Delagate object for handling event
private RailwaySignalEventHandler _railwaySignalEvent;
// Event Accessor
public event RailwaySignalEventHandler RailwaySignalEvent
{
add
{
lock (this)
{
_railwaySignalEvent += value;
}
}
remove
{
lock (this)
{
_railwaySignalEvent -= value;
}
}
}
// Invoke Event for subscribed clients
private void Notify()
{
if (_railwaySignalEvent != null)
_railwaySignalEvent.Invoke(this, Colour.Green);
}
// Test the Event Invocation
public void TestEvent()
{
Notify();
}
}
public class RailwayUser
{
private static RailwaySignal railwaySignal { get; set;} = new RailwaySignal("Signal1");
public RailwayUser()
{
railwaySignal.RailwaySignalEvent += this.Notice;
}
public static void TestNotification()
{
railwaySignal.TestEvent();
}
public void Notice(object sender, Colour color)
{
Console.WriteLine($"Notice Called, Colour is :: {color}, Sender is :: {((RailwaySignal)sender).Name}");
}
}
Result
Notice Called, Colour is :: Green, Sender is :: Signal1
Notice Called, Colour is :: Green, Sender is :: Signal1
Important Details
Signature of the event is, (object source, Colour e) which helps in passing the relevant information across to the RailwayUser called, We now know the RailwaySignal triggering the notification to the RailwayUser and its Colour value
Event / Delegate has same signature as called method (which is the basis of working of Delegate / function pointers)
For simplification RailwayUser is a non abstract class
Event is executed using Notify() method inside the RailwaySignal, we are calling it artificially using TestNotification() inside RailwayUser just for demo purpose, but ideally it shall be internally triggered and shall pass on current state like Colour
Pre-defined delegates like Func, Action are quite often used for similar notification mechanism, They internally works using similar mechanism, though declaring an explicit event which is internally a delegate is a well defined pattern, especially for the Ui controls
Standard events exposed by the .Net framework have the signature object sender, EventArgs e, where EventArgs can wrap all information from Event executor (RailwaySignal) to Event receiver (RailwayUser)
It seem like a Observer pattern.You can pass SubClass which inherit from RailwayUser object instance into RailwaySignal class
Your RailwayUser class need create public abstract void Notice(Colour state) method.
public abstract class RailwayUser
{
private string className;
public RailwayUser()
{
Type type = this.GetType();
className = type.Name;
}
public void PrintClassName()
{
Console.WriteLine(className);
}
public abstract void Notice(Colour state);
}
Driver class can inherit RailwayUser class then override Notice method.
public class Driver : RailwayUser
{
public override void Notice(Colour state)
{
Console.WriteLine($"Driver see the {state.ToString()}");
}
}
There are
List<RailwayUser> _watches contain observable object
use SubScript(RailwayUser user) subscription user on _watches List.
RailwayUser Notify() to invoke all your observable Notify method.
look like this.
public class RailwaySignal
{
private List<RailwayUser> _watches;
public Colour Stata { get; set; }
public RailwaySignal()
{
_watches = new List<RailwayUser>();
}
public void SubScript(RailwayUser user)
{
_watches.Add(user);
}
public void Notify()
{
foreach (RailwayUser u in _watches)
{
u.PrintClassName();
u.Notice(Stata);
}
}
}
sample:https://dotnetfiddle.net/GcdGMy
You can also use event to pass method into RailwaySignal then invoke Notify method.
public enum Colour
{
Green,
Red,
Disable
}
public abstract class RailwayUser
{
private string className;
public RailwayUser()
{
Type type = this.GetType();
className = type.Name;
}
public void PrintClassName()
{
Console.WriteLine(className);
}
public abstract void Notice(Colour state);
}
public class Driver : RailwayUser
{
public override void Notice(Colour state)
{
Console.WriteLine("Driver see the "+ state.ToString());
}
}
public class Controller : RailwayUser
{
public override void Notice(Colour state)
{
Console.WriteLine("Controller see the " + state.ToString());
}
}
public class RailwaySignal
{
public delegate void NoticeEvent(Colour state);
public event NoticeEvent Notifys;
public Colour Stata { get; set; }
public void Notify()
{
if (Notifys != null)
{
Notifys(Stata);
}
}
}
use like this.
RailwaySignal railway = new RailwaySignal() { Stata = Colour.Green};
railway.Notifys += new Driver().Notice;
railway.Notifys += new Controller().Notice;
railway.Notify();
sample : https://dotnetfiddle.net/GcdGMy

Update label through another class

I'm trying to call method Run in script1. Then from script1 call method alert or wait and try to update statusLabel in Form1. But this code has an error.
static Label status = this.Controls.Find("statusLabel", true).FirstOrDefault() as Label;
This code will only work in Form1. Because this return error in another classes. Maybe it is not correct and you know better solution.
P.S. I know how to solve this problem (see below "Not the best solution"), but the code will be ~ 10-30 new lines.
Project
Form1.cs
public partial class Form1 : Form
{
private void statusLabel_Click(object sender, EventArgs e)
{
}
private void Form1_Load(object sender, EventArgs e)
{
script1.Run();
...
script30.Run();
}
}
function.cs (Frequently used functions)
public class function
{
static Label statusLabel = this.Controls.Find("statusLabel", true).FirstOrDefault() as Label;
static public void alert(string str)
{
statusLabel.Text = str;
}
static public void wait(int sec)
{
int i = 0;
while (i++ < sec)
{
statusLabel.Text = "Wait: " + (sec+1-i).ToString();
Thread.Sleep(1000);
}
}
}
script1.cs (script1,script2 ... it is about 30 mini programs)
public class script1
{
static public void Run()
{
function.alert("Script1 is running");
function.wait(5);
function.alert("Script1 is done");
}
}
Not the best solution
remove in function.cs
static Label status = this.Controls.Find("statusLabel", true).FirstOrDefault() as Label;
Form1.cs
public partial class Form1 : Form
{
private void Form1_Load(object sender, EventArgs e)
{
script1.Run(this.statusLabel);
}
}
function.cs
public class function
{
private Label _statusLabel;
public scriptClass(Label statusLabel)
{
_statusLabel = statusLabel;
}
}
script1.cs (script1,script2 ... it is about 30 mini programs)
public class script1
{
static public void Run(Label statusLabel)
{
function _function = new function(statusLabel);
}
}
The statusLabel object is owned by, and should be encapsulated and hidden by, the Form1 class. To ensure good decoupling of your classes, as well as proper data hiding, only the Form1 class should be directly accessing it. And it should (by default) be able to access it via a field named statusLabel (i.e. no need to call this.Controls.Find() (nor should that even work from the function class, since that class also is not the owner of the object, nor of a Controls property).
The correct way to do this is for the script1 class to expose a StatusText property, and an event that is raised when the property value changes. There are two canonical ways to implement the event:
Implement an event named StatusTextChanged
Implement the INotifyPropertyChanged interface
Note that in your example, #2 is not an option because you are using static classes to implement your scripts. IMHO this is inadvisable for a variety of reasons, but since #1 is a perfectly fine solution I won't belabor that point. :)
The first looks like this:
class script1
{
public static string StatusText { get; private set; }
public static event EventHandler StatusTextChanged;
static public void Run()
{
ChangeStatusText("Script1 is running");
function.wait(5);
ChangeStatusText("Script1 is done");
}
static void ChangeStatusText(string text)
{
StatusText = text;
EventHandler handler = StatusTextChanged;
if (handler != null)
{
handler(null, EventArgs.Empty);
}
}
}
Then in Form1:
public partial class Form1
{
private void Form1_Load(object sender, EventArgs e)
{
script1.StatusTextChanged += (sender1, e1) => statusLabel.Text = script1.Text;
script1.Run();
...
script30.StatusTextChanged += (sender1, e1) => statusLabel.Text = script30.Text;
script30.Run();
}
}
Note in the above, each scriptX class has to reimplement the event. You could instead make a base class that each of the scriptX classes inherits, and which contains the event in question. Then the Form1 class need only subscribe to the one base class event. It would also address, or at least minimize the hassle of, the issue of leaving event handlers subscribed to 30 different events.
Of course, in this case then the Form1 class won't know which script is updating the text, but maybe that doesn't matter in your case.
Also note that if you did make the scriptX classes non-static, you might then again run into the issue of having to subscribe multiple times. But that is much more easily handled, since it seems certain in that case you'd use a base class, and so it would be easy to generalize the "subscribe, run script, unsubscribe" logic into a helper method.

how to use interface in C#

Using C# .NET 4.0, Visual Studio 2010.
Well at the moment I'm looking into de-coupling of Classes and using interfaces.
I've implemented a Solution from another post to test if I could get it working but unfortunately I have never used an interface ever.
So here's the basics of what I have:
Form1:
partial class Form1 : InterfacePareto
{
public string myTest
{
get { return herpTxt.Text; }
set { herpTxt.Text = value; }
}
}
Interface:
interface InterfacePareto
{
string myTest { get; set; }
}
MyWorkingOutClass:
Class MyWorkingOutClass
{
private readonly InterfacePareto pare;
public MyWorkingOutClass(InterfacePareto pare)
{
this.pare = pare;
}
private void Testtime()
{
string firstName = pare.myTest;
pare.myTest = firstName + " extra";
}
}
The purpose:
The plan at the moment is to get the text from the forms textbox. Then pass it to the working class. The working class then does whatever calculations etc needed, then passes the result back to the forms textbox.
My question is, is my code along the right tracks. If yes, then what am I missing/doing wrong? Or if anyone thinks this is not the right way of achieving what I need, do they have any suggestions?
Many thanks!
I've just tested code and this works fine for me:
public partial class MainForm :Form, InterfacePareto //My main form inheriting Form class and interface
{
public MainForm()
{
InitializeComponent();
}
public string myTest
{
get { return herpTxt.Text; }
set { herpTxt.Text = value; }
}
private void button1_Click(object sender, EventArgs e)
{
//On button click create MyWorkingOutClass instance and pass MainForms instance
MyWorkingOutClass mc = new MyWorkingOutClass(this);
//After this line text box content will change
mc.Testtime();
}
}
//Changed modifier to public
public interface InterfacePareto
{
string myTest { get; set; }
}
//Changed modifier to public
public class MyWorkingOutClass
{
private readonly InterfacePareto pare;
public MyWorkingOutClass(InterfacePareto pare)
{
this.pare = pare;
}
//Changed modifier to public
public void Testtime()
{
string firstName = pare.myTest;
pare.myTest = firstName + " extra";
}
}
This should work fine.
There is one issue you will get when the MyWorkingOutClass does its work on a different thread than the UI thread.
To solve that you might want to change the implementation on the form to switch to the UI thread.

RegisterCallback<T>(Action<T> func) , how do I store this function pointer in a class?

I'm trying to expose an API such that, I do the following
RegisterCallback<T>(Action<T> func)
{
someObj.FuncPointer = func;
}
Later on, I call func(obj) .. and the obj is of type T that the user said.
More concrete example:
var callbackRegistrar = new CBRegistrar();
callbackRegistrar.RegisterCallback<ISomeClass>(SomeFunc);
public static void SomeFunc(ISomeClass data)
{
//
}
EDIT: So I may not have been clear, so I'll add more code:
I want to make only "one" object of CBRegistrar, and connect it with many Callbacks, as such:
var callbackRegistrar = new CBRegistrar();
callbackRegistrar.RegisterCallback<ISomeClass>(SomeFunc);
callbackRegistrar.RegisterCallback<ISomeOtherClass>(SomeFunc2);
...
In fact the above code is called by reflecting over a directory of plugins.
The user puts this in their code -->
public static void SomeFunc(ISomeClass data)
{
//
}
public static void SumFunc2(ISomeOtherClass data)
{
//
}
It looks to me as if this is not possible using Generics, etc. What it looks like I might have to do is make an interface called IPlugin or something, and ask the user to do this ..
[PluginIdentifier(typeof(ISomeClass))]
public static void SomeFunc(IPluginData data)
{
var castedStuff = data as ISomeClass; // ISomeClass inherits from IPluginData
}
Seems like asking the user to do stuff that we should take care of, but anyway ...
You need a Action<T> func to store it in. There is a semantic check to make here: if someone calls RegisterCallback twice (with different values), do you want to replace the callback, or keep both ? Assuming the latter, someObj probably wants an event (indeed, this entire API could be exposed as an event), so - in the someObj class:
public event Action<T> FuncPointer;
private void InvokeCallback(T data) {
var handler = FuncPointer;
if(handler != null) handler(data);
}
Noting that RegisterCallback could be replaced entirely, still keeping the data on obj:
public event Action<T> Completed {
add { obj.FuncPointer += value; }
remove { obj.FuncPointer -= value; }
}
Then usage would be:
var callbackRegistrar = new CBRegistrar();
callbackRegistrar.Completed += SomeFunc;
Callback functions are not much used in C#. They've been replaced by events which are more elegant and easier to work with.
class CBRegistrar
{
public delegate void ActionRequiredEventHandler(object sender, ISomeClass e);
public event ActionRequiredEventHandler ActionRequired;
void RaiseActionRequiredEvent(ISomeClass parm)
{
if ( ActionRequired != null)
{
ActionRequired(this, parm);
}
}
}
class APIConsumer
{
var callbackRegistrar = new CBRegistrar();
public APIConsumer()
{
callbackRegistrar.ActionRequired += SomeFunc;
}
public void SomeFunc(object sender, ISomeClass data)
{
}
}
If you still want to use Callbacks, you can use Delegates which are more or less function pointer.
The CBRegistrar will need to be generic (if it's OK to keep a single callback type) or it can do some internal casting (if several callback types need to be registered).
public class CBRegistrar<T>
{
private Action<T> callback;
private Dictionary<Type, object> callbackMap;
public CBRegistrar()
{
this.callbackMap = new Dictionary<Type, object>();
}
public void RegisterCallback(Action<T> func)
{
this.callback = func;
}
public void RegisterGenericCallback<U>(Action<U> func)
{
this.callbackMap[typeof(U)] = func;
}
public Action<U> GetCallback<U>()
{
return this.callbackMap[typeof(U)] as Action<U>;
}
}
public interface ISomeClass
{
string GetName();
}
public class SomeClass : ISomeClass
{
public string GetName()
{
return this.GetType().Name;
}
}
namespace ConsoleApplication
{
class Program
{
static void Main(string[] args)
{
var callbackRegistrar = new CBRegistrar<ISomeClass>();
callbackRegistrar.RegisterCallback(SomeFunc);
callbackRegistrar.RegisterGenericCallback<ISomeClass>(SomeFunc);
var someone = new SomeClass();
callbackRegistrar.GetCallback<ISomeClass>()(someone);
}
public static void SomeFunc(ISomeClass data)
{
// Do something
Console.WriteLine(data.GetName());
}
}
}

Should I go with reflection or delegates (C#)?

In one of my previous questions I explained about a form class that contain form field objects to save data in a user profile object (using profile provider).
The code is here bellow. Basically what I would like to accomplish is to pass as a parameter to my form field objects the field of the Profile object that they should interact in order to save the data later on.
You can see that in the following line:
//LastNameFormLine is an control that was added to my form page.
//The ProfileField parameter stores the field of the UserProfile object that is being manipulated by this control
LastNameFormLine.ProfileField = "UserProfile.LastName";
I was reading about reflection to be able to save this value in the UserProfileVisitor class, but I came across this concept of delegate in C# which I am not sure yet if I fully grasp.
Is it possible to delegate the ProfileField to a property on my UserProfile class? Or should I forget about it and go with reflection?
What would you suggest?
public partial class UserProfileForm : CustomIntranetWebappUserControl
{
protected override void OnInit(EventArgs e)
{
//AutoEventWireup is set to false
Load += Page_Load;
CancelLinkButton.Click += CancelButtonClickEvent;
SaveLinkButton.Click += SaveButtonClickEvent;
base.OnInit(e);
}
private void SaveButtonClickEvent(object sender, EventArgs e)
{
VisitFormFields();
}
private void VisitFormFields()
{
var userProfileVisitor = new UserProfileVisitor();
foreach (var control in Controls)
{
if (control is FormFieldUserControl)
{
var formField = (FormFieldUserControl) control;
formField.Visit(userProfileVisitor);
}
}
userProfileVisitor.Save();
}
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
{
BindText();
}
}
private void BindText()
{
LastNameFormLine.LabelText = string.Format("{0}:", HomePage.Localize("Last Name"));
LastNameFormLine.InputValue = UserProfile.LastName;
LastNameFormLine.IsMandatoryField = true;
LastNameFormLine.IsMultilineField = false;
LastNameFormLine.ProfileField = "UserProfile.LastName";
//... the rest of this method is exactly like the 4 lines above.
}
}
public abstract class FormFieldUserControl : CustomIntranetWebappUserControl
{
public string ProfileField { get; set; }
public abstract void Visit(UserProfileVisitor userProfileVisitor);
}
public partial class FormLineTextBox : FormFieldUserControl
{
//... irrelevant code removed...
public override void Visit(UserProfileVisitor userProfileVisitor)
{
if (userProfileVisitor == null)
{
Log.Error("UserProfileVisitor not defined for the field: " + ProfileField);
return;
}
userProfileVisitor.Visit(this);
}
}
public class UserProfileVisitor
{
public void Visit(FormLineTextBox formLine)
{
// The value of formLine.ProfileField is null!!!
Log.Debug(string.Format("Saving form field type {1} with profile field [{0}] and value {2}", formLine.ProfileField, formLine.GetType().Name, formLine.InputValue));
}
// ... removing irrelevant code...
public void Save()
{
Log.Debug("Triggering the save operation...");
}
}
Delegates are not for properties. However, Reflection is slow, may have issues with code security and it's not typesafe and may lead to runtime instead of compile-time problems on naming errors due to the late-bound nature.
That said, you may want to use getter and/or setter methods and use delegates on those.

Categories

Resources