Store methods in arrays - c#

I have an if statement in a foreach and was wondering if I can call a different method depending on what items are true without having to do a switch or if statements for all of them.
foreach (var item in buttons)
{
if(item.isClicked)
//call item method
}
buttons is not of class Buttons
What I'm looking for is like
button[0] calls method start()
button[1] calls method options()
Is there any way I can do this?

You could do something like this:
private void DoStuff(params Action[] methods) {
for (int i = 0; i < buttons.Length; i++) {
if (buttons[i].isClicked) {
methods[i]();
break;
}
}
}
Then, you would say:
DoStuff(start, options);
Where start is the method called for the first button, options for the second, x for n.. etc.

Assuming your buttons don't support proper events, I suppose what you're looking for is a delegate. There are several ways to do this, but the most obvious thing that comes to mind is something like this:
Action[] actions = new Action[2]; // create an array of actions, with 1 action for each button
actions[0] = start;
actions[1] = options;
...
for(var i = 0; i < buttons.Length; i++)
{
if(buttons[i].isClicked)
actions[i]();
}

There are a couple of ways to achieve this, which way you use really depends on how much access you have to modify the class of your "buttons" (which you haven't actually told us what it is).
Option 1: Add a new member to the class (provided the class of 'buttons' is your own class)
Modify your class to have a new member, called Action or some such name. This member will be a Delegate (note: You can use a more specific type like Action<T> if you know each button's action has an identical method signature. Once you have this member declared, you can easily call it. Pseudocode:
public class MyButton {
public bool isClicked { get; }
public Delegate action { get; }
}
foreach (var item in buttons) {
if(item.isClicked)
((Action)item.action)(); // assuming that your "action" is a method which returns nothing and takes no arguments, cast to a more appropriate type if needed
}
Option 2: Map each button to an action
Similar principal to Option 1, except because you can't directly modify the backing class you'll have to bind actions to buttons after the fact. You can create a map (or Dictionary<TKey,TValue> in C#) to map the buttons to their actions. To do this, create a new Dictionary and add each button as a key alongside its action:
// Declared at class-scope
private readonly Dictionary<MyButton,Delegate> _actions = new Dictionary<MyButton,Delegate>(); // I don't know what type 'buttons' is so I'm substituting it with "MyButton"
// In some initializer for the class (i.e the constructor)
_actions.Add(buttons[0], start)
_actions.Add(buttons[1], options)
// .. etc
// Then your loop becomes something like:
foreach(var item in buttons) {
if (item.isClicked && _actions.ContainsKey(item)) {
((Action)_actions[item])();
}
}

Related

Is there a way to pass the DbSet<T> into the page?

I have the window with the page. The page displays a data from the my database. Also, on the window the buttons are placed, whose contents is according to the tables names of the database. These buttons switchs the page's content.
For example, this is the btnUsers button's click event, which displays the "Users" table:
void btnUsers_Click(object sender, RoutedEventArgs e) {
this.FrameMain.Navigate(new pageTable(Context.ctx.Users, ...));
}
The pageTable is the my "generic" page, that receives the Users class. Here is its constructor, which doesn't works:
public pageTable(dynamic table, ...) {
InitializeComponent();
TableTemplate<dynamic>.Init(table, ...);
}
Here is the my generic class, that operates on the DbSet<T>:
static class TableTemplate<T> {
internal static void Init(T table) {
foreach (string f in Foo(table, ...) {
...
}
}
}
The Foo method just extracts the columns from the DbSet<T> table:
internal static string Foo<T>(T item, ...) {
...
}
The point is, that the application terminates when I try to get the data from the table, at the button's event, used this generic approach.
I noticed, that at the Foo method, during the debug, the T type is differs, depending on the way, with which I pass the DbSet<T>:
if I explicitly initialize a new class instance (for the test):
static class TableTemplate<T> {
internal static void Init(T table) {
foreach (string f in Foo(new Users(), ...) {
...
}
}
}
, then the T type is System.Data.Entity.DynamicProxies.Users_E006B3..., and the Foo method is works;
without the explicitly initialization the T type is System.Data.Entity.DbSet`1[Namespace.Users], and the Foo method isn't works.
Is there a possibility to pass the generic entity class into the page? I don't know if XAML has a generic classes support, to use the generic pageTable<T> page. It could be a solution, but I suppose there is a more neat way to pass the entity.
I found the solution, and it doesn't use the generic page.
Well, when I tried to print the table content, I discovered, that pass a structured query into the TableTemplate.Init(). I remember, that never used the dbContext.TableClass as a function argument before, always converting the TableClass into the list.
I confess, I don't understand the EntityFramework and didn't expect such a result. Generally, I used the object type and already forgot why used the dynamic type...
I decided to pass the DbSet<T>, converted to the list (and this, as I understand it, are the different thigns) into the page's constructor, instead of the DbSet<T>. But, because I doesn't use the general page, I converted the items of this list into the object:
void btnUsers_Click(object sender, RoutedEventArgs e) {
this.FrameMain.Navigate(new pageTable(Context.ctx.Users.ToList<object>()));
}
Now, the pageTable page's constructor is next:
public pageTable(List<object> table) {
InitializeComponent();
TableTemplate<object>.Init(table, ...);
}
And, the Init method of the TableTemplate class is next:
internal static void Init(List<T> tableList) {
if (tableList.Count > 0) {
foreach (string f in Foo(tableList[0], ...) {
...
}
}
}
I haven't figured out how to display only the table's columns names, if tableList is empty. Thus, in this case, for now the page displays the empty DataGrid without the columns names. Nevertheless, I am glad, that could do I wanted.
At last, I will say, that indirectly agree with Xerillio.

Programmatically Add Objects to a UnityEvent and set the Function

I am trying to add an object to a UnityEvent listener and set that listeners function to Raise() function as the trigger. Like the below screenshot. That way I won't forget to drag and drop the object, or by chance selected the wrong function;
I have some a custom GameEvent that I use through out my game that contains the Raise() function;
public class GameEvent : ScriptableObject
{
private readonly List<GameEventListener> eventListeners = new List<GameEventListener>();
public void Raise()
{
for(int i = eventListeners.Count -1; i >= 0; i--)
eventListeners[i].OnEventRaised();
}
public void RegisterListener(GameEventListener listener)
{
if (!eventListeners.Contains(listener))
eventListeners.Add(listener);
}
public void UnregisterListener(GameEventListener listener)
{
if (eventListeners.Contains(listener))
eventListeners.Remove(listener);
}
}
To make my life easier, I have created an Editor script that will populate two UnityEvents for me.
I can find the two custom GameEvents I want to add. OnCameraWillTransition and OnCameraFinishedTransition by using:
string[] eventAssets = AssetDatabase.FindAssets("OnCamera t:GameEvent", new[] { "Assets/_Scripts/Library/Camera/Events" });
Then I loop through each of the two events and check their names, and add them to whatever class needs them set. In this example, I am using ProCamera2D and it has two events that I want to set. It's referenced in the screenshot above. This is just an example. I would like to be able to pre-poulate any class that has some UnityEvent.
ProCamera2DRooms pr = m_cam.gameObject.AddComponent<ProCamera2DRooms>();
foreach (string s in eventAssets)
{
string path = AssetDatabase.GUIDToAssetPath(s);
if (path.Contains("OnCameraFinishedTransition"))
{
Debug.Log("OnCameraFinishedTransition");
GameEvent e = (GameEvent)AssetDatabase.LoadAssetAtPath(path, typeof(GameEvent));
// This doesn't work, and I have tried different methods
pr.OnStartedTransition.AddListener( (e)=> {e.Raise()} ) );
}
//if (path.Contains("OnCameraWillTransition"))
//Haven't Started
}
Is there any way to pre-populate UnityEvent's programmatically?
I tried to do the same just a few days ago.
I had an example script made just to activate/deactivate a unityevent:
void SetEventTriggerState(EventTrigger ET, EventTriggerType ETType, string MethodName, UnityEventCallState NewState) {
for (int i = 0; i < ET.triggers.Count; i++) {
EventTrigger.Entry Trigger = ET.triggers[i];
EventTrigger.TriggerEvent CB = Trigger.callback;
for (int j = 0; j < CB.GetPersistentEventCount(); j++) {
if (CB.GetPersistentMethodName(j) == MethodName && Trigger.eventID == ETType) {
CB.SetPersistentListenerState(j, NewState);
}
}
}
}
You call it like that (the button that activate the trigger event, event type and event name that you need to change, new state that you need to set)
SetEventTriggerState(actionButtonEventTrigger, EventTriggerType.PointerDown, "JumpButton", UnityEventCallState.EditorAndRuntime);
I tried to add a line like this:
CB.SetPersistentTarget(j, newGameObject); //after the SetPersistentListenerState line
But I discovered that there is no way to do something like that (there is only the GetPersistentTarget method and I found no alternative way to change the target object at runtime).
Not sure if you can add it at runtime but there is an alternative way to do everything at runtime that I found:
First you need to implement the interface you need:
IDragHandler, IPointerUpHandler, IPointerDownHandler
Those are just examples (I'm not sure what you need for the ProCamera2D since I'm not using it), the first one is for the Drag Event, the second one is for the PointerUp event and the last is for the PointerDown event.
After that I just implement the method I want to use with the object I need to use:
public virtual void OnPointerDown(PointerEventData ped) {
currentObject.GetComponent<ScriptOfThatObject>().MethodIWantToUse();
}
to decide what Object will use that method I created a setter method
public GameObject CurrentObject {
set => CurrentObject= value;
}
And I set that GameObject OnTriggerEnter
public void OnTriggerEnter(Collider other) {
publicScriptOfMyButtonReference.CurrentObject = other.gameObject;
}
This is just an example of how to implement Event without using the UnityEvent.EventTrigger component and just use code.
I will not be able to be more specific since I don't use that Camera script but you should be able to implement a solution with those few things in mind.

How to properly declare class variables (CUIT Controls)

I am setting up Coded UI Tests for WPF application and I want to use code approach instead of record-and-generate-code approach. I'd like to use page objects trough code and I need to declare control (buttons, tabs, etc.) variables in page objects that would be used by multiple functions.
I tried declaring the variable in a class and adding properties in constructor (pendingButton1)
and creating function which returns the control and assigning to a variable in a class (pendingButton2) but neither worked.
It works when I declare the variable (or create the variable by function) within the function that I want to use the variable in (pendingButton3 and 4).
public partial class Press : Header
{
WpfToggleButton pendingButton1 = new WpfToggleButton(_wpfWindow);
WpfToggleButton pendingButton2 = Controls.Press.getPendingButton(_wpfWindow);
public Press(WpfWindow wpfWindow):base(wpfWindow)
{
this.pendingButton1.SearchProperties[WpfControl.PropertyNames.AutomationId] = "Tab1Button";
}
public void clickPendingButton() {
WpfToggleButton pendingButton3 = new WpfToggleButton(_wpfWindow);
pendingButton3.SearchProperties[WpfControl.PropertyNames.AutomationId] = "Tab1Button";
WpfToggleButton pendingButton4 = Controls.Press.getPendingButton(_wpfWindow);
Mouse.Click(pendingButton1); //UITestControlNotFoundException
Mouse.Click(pendingButton2); //UITestControlNotFoundException
Mouse.Click(pendingButton3); //This works
Mouse.Click(pendingButton4); //This works
}
}
I'd like to make it work when I declare the pendingButton outside clickPendingButton() function since it is used in multiple other functions.
The helper function Controls.getWpfButton() return just properties of the button, not "real" button. It has to be used in a constructor, then it can be used anywhere within the class. I wouldn't say its best practice but it works for me.
Press.cs
public partial class Press : SharedElements
{
private WpfButton pendingButton;
public Press(WpfWindow wpfWindow):base(wpfWindow)
{
pendingTab = Controls.getWpfButton(_wpfWindow, "Tab1Button");
}
public void clickPendingButton() {
Mouse.Click(pendingButton);
}
}
Controls.cs
internal static WpfButton getWpfButton(WpfWindow wpfWindow, string AutomationId)
{
WpfButton button = new WpfButton(wpfWindow);
button.SearchProperties[WpfControl.PropertyNames.AutomationId] = AutomationId;
return button;
}
What you want appears to be exactly the sort f code that the Coded UI record and generate tool generates. It creates many pieces of code that have a structure of the following style:
public WpfToggleButton PendingButton
{
get
{
if ((this.mPendingButton == null))
{
this.mPendingButton = new WpfToggleButton( ... as needed ...);
this.mPendingButton.SearchProperties[ ... as needed ...] = ... as needed ...;
}
return this.mPendingButton;
}
}
private WpfToggleButton mPendingButton;
This code declares the button as the class property PendingButton with a private supporting field that has an initial and default value of null. The first time that property is needed the get code executes the required search and saves the found control in the private field. That value is then returned in each subsequent usage of the property. Note that assigning null to the supporting field can be done to cause a new search, as demonstrated in this Q&A.

How to store a list of Cases from Switch Statement?

In my program I have a listbox that when the user double clicks an object it looks to a switch statement to see what event should occur. As the list begins getting larger I'm curious if there is a way to avoid having to maintain the list of objects in 2 places (once in a list to Add to the listbox, and once in the switch statement.
Is there a way to index/read/store the various Cases of my switch statement, then add them as objects to my listbox?
Example: (doesn't work, just a theory)
Switch (n)
ForEach (Case c in Cases)
{
arrayCases.Add(c);
}
listbox.Items.AddRange(arrayCases);
EDIT:
Going on the Dictionary recommendations I now have:
public void SetDictionary()
{
//add entries to the dictionary
dict["cat"] = new Action(Cat);
dict["dog"] = new Action(Dog);
//add each dictionary entry to the listbox.
foreach (string key in dict.Keys)
{
listboxTest.Items.Add(key);
}
}
//when an item in the listbox is double clicked
private void listboxTest_DoubleClick(object sender, EventArgs e)
{
testrun(listboxCases.SelectedItem.ToString());
}
public void testrun(string n)
{
//this is supposed to receive the item that was double clicked in the listbox, and run it's corresponding action as defined in the dictionary.
var action = dict[n] as Action action();
}
I believe that my code above is mostly correct and that I'm understanding it, however the action line:
var action = dict[n] as Action action();
Shows an error stating 'action' is expecting a ';'. Is my logic here accurate? If so, why is the action call incorrect?
Dictionary<string, Action> is the way to avoid. Dictionary.Keys becomes ListBox.Items.
switch(n) becomes
var action = dict[n] as Action
action();
I suggest to move your operations into separate classes. Create a base class for your operations like the following one. I added a field for the form because you probably have to interact with your form. You can also pass in other objects if required.
internal abstract class Operation
{
protected readonly MyForm form = null;
protected Operation(MyForm form)
{
this.form = form;
}
public abstract String DisplayName { get; }
internal abstract void Execute();
}
Then derive one class for each operation.
internal sealed class DoThis : Operation
{
internal DoThis(MyForm form) : base(form) { }
public override String DisplayName
{
get { return "Do this!"; }
}
internal override void Execute()
{
// Code to do this. You can use this.form to interact with
// your form from this operation.
}
}
internal sealed class DoSomethingElse : Operation
{
internal DoSomethingElse(MyForm form) : base(form) { }
public override String DisplayName
{
get { return "Do something else!"; }
}
internal override void Execute()
{
// Code to do something else.
}
}
Now you can add all your operations to the list box
this.lsitBox.Items.Add(new DoThis(this));
this.lsitBox.Items.Add(new DoSomethingElse(this));
and set the display member property.
this.listBox.DisplayMember = "DisplayName";
Finally execute the selected operation in the event handler.
((Operation)this.listBox.SelectedItem).Execute();
This pattern gives clean separation between all your operations and makes future extensions easy and clean. For example you could add a property CanExecute to all operations if you have to check if a operation is currently available. Or if you have to support localization it is easy to add logic for presenting the name of the operation in the current UI language.
Another scenario that is easily supported is if you have some code common to all operations for example logging, security checks, performance measuring and things like that.
internal abstract class Operation
{
protected readonly MyForm form = null;
protected Operation(MyForm form)
{
this.form = form;
}
public abstract String DisplayName { get; }
protected abstract void ExecuteCore();
internal void Execute()
{
Logger.Log("Executing operation " + this.DisplayName);
try
{
this.ExecuteCore();
Logger.Log("Executing operation " + this.DisplayName + " succeeded.");
}
catch (Exception exception)
{
Logger.Log("Executing operation " + this.DisplayName + " failed.", exception);
throw;
}
}
}
Note that you now have to override ExecuteCore() instead of Execute().
One final thought - using an interface IOperation instead or in combination with the abstract base class may be helpful, too. This removes the need that all operation inherit from the same base class because this might sometimes be inconvenient. But I omitted this to not overengineere this even more.
You can't* enumerate case of switch with normal code.
What you can do instead is to replace switch with map of "action name" to "action handler" and than you'll be able to reuse this map for list of action names listbox. See Tilak's answer for sample.
*) If you are really inquisitive you can enumerate choices of switch. C# code is transformed to IL and IL can be read with code. So you can get IL for a method, write (or get existing - Parser for C#) parser for IL and find implementation of switch inside the method, pick all cases. You can even go straight to C# source at build time - but it is even more involved than IL parsing.
Yes there is a way to do this by making a dictionary of lambdas.
void Main()
{
// set up your dictionary
Dictionary<string,Action> myList = new Dictionary<string,Action> {
{ "one", () => { Console.WriteLine("One function"); } },
{ "two", () => { Console.WriteLine("Two function"); }},
{ "three", () => { Console.WriteLine("Three function"); }}
};
// do a "switch" (that is invoke a function that corresponds to a name)
myList["one"]();
// loop the list of keys (that is get a list of all the names)
foreach (string key in myList.Keys)
Console.WriteLine(key);
}
the output of this program:
One function
one
two
three
Also note -- you can add to this "switch" dynamically like this (which is cool and something you can't do with a classical switch statement.)
myList.Add("four",() => { Console.WriteLine("Four function is dynamic"); });
It sounds to me like the number of cases in your switch are going to change a lot. If this is true, then you might want to consider using a mechanism other than a switch statement. Perhaps you want to do something like Alexi Levenkov suggests, and then iterate a list of the stored Action Names and execute the associated handler. This way you will avoid having to add the action name to the action map and then add it to the switch.

C# Dynamic extends a object

is it possible to extends a existing object ?
i have the code
var record = new
{
id,
name
};
and have a list of anonymous objects
var list = new List<object>(){ object1, object2 };
Can i add them later to the object ?
Like something as
foreach (var o in list)
{
record.add(o);
}
that i will get this as result
var record = new
{
id,
name,
object1,
object2
};
In short, no. At least, not with anonymous types. There are two approaches here; dynamic might give you what you want, but is fiddly for combining. Other than that, a basic property bag - even simply Dictionary<string,object> would do. The only difference being that:
obj.id
becomes
obj["id"]
There is a more fundamental problem, though, in trying to combine a list (each of which is largely anonymous) with properties in a single step. You can do this for data-binding purpose via custom property models, but it is... tricky.
What you can do is create a class Extension. It is not possible to add new methods in the runtime, but you can do something like this:
public class OneClass
{
private List<object> items;
public List<object> Items { get { return items; } }
public void AddOne(object item)
{
items.Add(item);
}
}
if you want to extend this class behavior, you can write an extension class. Like this:
public static class OneClassExtensions
{
public void AddMany(this OneClass self, params object[] items)
{
foreach(object item in items)
{
self.Items.Add(item);
}
}
}
This way you can call this extension method from your OneClass objects:
OneClass obj = new OneClass();
obj.AddOne("hello");
obj.AddMany("Hello", "world"); // Extension method
There are some rules to follow:
The extension class must have the `static' modifier
you need to put the `this' prefix before the first argument. This argument would be the object itself.
In order to use this extension class in your code, you must use the namespace that contains that extension class, like `using Some.Namespace.That.Has.An.Extension' in every .cs file where you want to use extension methods.
In case anyone runs into this question in the future, I have recently published a library to do exactly this. You can find it on nuget.org - it's called (unsurprisingly) ObjectExtend.
You can install it by grabbing it from Nuget or via your favourite package manager. You can also check out the source code, a brief introduction, or a detailed overview of how it works.
The short version is - install the package, make sure you import the namespace with using Rophuine.LINQPad.ObjectExtend;, and now you should be able to call .Extend on your objects.
A caveat: this is a great technique for exploratory coding, but I recommend against it for anything which will be maintained or go to production.
Since .net4 you could use ExpandoObject to do stuff like that.
For example:
var objs = new List<ExpandoObject>();
for (var i = 0; i < 10; i++)
{
dynamic eObj = new ExpandoObject();
eObj.Property = i;
objs.Add(eObj);
}
foreach (dynamic obj in objs)
{
obj.Property2 = "bubuValue" + obj.Property;
obj.Property3 = "bubuValue" + obj.Property2;
}
foreach (dynamic obj in objs)
{
Console.WriteLine(obj.Property3);
}

Categories