List of delegates and invoking - c#

I am creating a smaller RPG game in ASP.NET. In this game I have an items architecture, where each item has some methods. For instance, all items should share a method like "Drop", "Examine" and "Use". Some items will have to be extended with methods like "Operate", "Calculate" and such.
So far, I have created the following object GameActionList:
public delegate void MyDelegate();
public class GameActionList
{
public List<MyDelegate> Items = new List<MyDelegate>();
public void Add(MyDelegate del)
{
Items.Add(del);
}
public void CallDelegates()
{
foreach (MyDelegate myDelegate in Items)
{
myDelegate();
}
}
}
I have a BaseItem class, which has this GameActionList. The get property of this in the BaseItem class is like this:
public GameActionList Actions
{
get
{
GameActionList actions = new GameActionList();
actions.Add(this.Drop);
actions.Add(this.Examine);
return actions;
}
}
This is fine, BUT... I have some problems!
My problem
I need a way more generic GameActionList. I need to have a list of not only voids, but also functions.. Also, I need both methods with parameters and without parameters.
For instance: The Drop method will need a Player object, so he can Drop the item. The Examine method will need to return a string descriping the item.
Also, I need some data which I don't know when I Initialize the GameActionList: I first know these data when I invoke the method...
So I have two questions:
How do you extend the GameActionList, so it can contain a list of both voids and functions andalso these both can have parameters or not.. (AND DOES IT EVEN MAKE SENSE??)
How can I give some data to the method later in the cycle, like when invoking?
Also... This might be a very stupid way to do it, so if you have some way more elegant solution.. I'm more than ready to hear it!
Thanks a lot...!
Lars

you most probably need Action , Func delegates
Func
Action

Related

Where to place a method that shares logic of two classes

I have two classes, BuildingHandler and TestHandler.
BuildingHandler contains a method to LoadBuildings and TestHandler contains one to LoadTests()
Now I would like to create a function called LoadBuildingTests.
I'm unsure what handler to place this in as the functionality relates to both Buildings and Tests.
I'm leaning towards having LoadBuildingTests in the BuildingHandler, then once IDs have been retrieved calling TestHandler.LoadTests();
Does this seem reasonable, or am I approaching it the wrong way? Should I be looking into interfaces, or another approach?
I'd leave LoadBuildingTests inside BuildingHandler and pass in the TestHandler as an argument:
public class BuildingHandler
{
public static void LoadBuildingTests(TestHandler testHandler)
{
if (testHandler == null) throw ....
var building = LoadBuilding();
var tests = testHandler.LoadTests(building.Id);
//....
}
//..
}
Equally valid would be to implement the method in TestHandler and pass in the BuildingHandler as the argument but I have insufficient context to decide which is better. At first glance, I like the first option more.

Pass object into method without adding argument to method?

I have a simple interface called IEvent and it just contains this one method:
void Execute();
I have several derived classes from this interface and one of them needs access to an object that the caller of the method owns. The object is used in this fashion:
using (MyObject object = new MyObject(this.MessageService)
{
foreach (IEvent myEvent in eventList)
{
myEvent.Execute(); // <--- I need to pass object without adding argument here if possible?
}
}
I would add the object as a field in the derived class that needs access to it, but by the time I get to this part of the code, the IEvent objects are already constructed and running on a background thread. Currently, the only way I can think of is to add a setter in the IEvent interface for this object, but then I am exposing a field that most derived classes won't care about and doesn't seem like a clean solution.
I would add it as an argument to Execute(), but the problem is that the object belongs to an assembly that the assembly that contains IEvent doesn't know about (and don't want it to know about) and again 99% of the events don't care about this object anyway. Is there a better way to accomplish what I am trying to do here?
"If a class that implements IEvent does not/can not implement all the methods specified by IEvent the same way as they are declared in IEvent, that class should not implement IEvent in the first place." - Sweeper
So there's probably something wrong with your design of the whole program. I think you better revise your design a little bit and change some relationships between the classes and interfaces.
If you don't want to do that, there is another (not recommended) way to solve this problem.
Suppose your method caller is of type MethodCaller. You just change the declaration of Execute in the interface to this:
void Execute(MethodCaller obj = null);
And all the classes that implement IEvent can ignore the parameter except the class you mentioned in your question.
I'm going to piggyback on Jon Skeet's amazing knowledge of C#, .NET, CLR, IL and everything that surrounds any of those topics. You can't get to the instance of the calling object and especially the local varaible in the calling method. You can get its type, you can get the calling method through StackTrace, for example (StackTrace.GetFrames()), but none of those are going to do you any good in this situation. What you're trying to accomplish would require some heavy dive into the debugging API. As far as walking the stack, here's a quick sample I created to try see if I can figure something out for you (I made assumptions in regards to how your program is structured... obviously it's not a one to one sample):
using System;
using System.Collections.Generic;
using System.Diagnostics;
namespace SampleApp
{
class Program
{
static void Main(string[] args)
{
var eventList = new List<IEvent> { new SomeClass() };
using (MyObject obj = new MyObject(new MessageService()))
{
foreach (IEvent myEvent in eventList)
{
myEvent.Execute();
}
}
}
}
public interface IEvent
{
void Execute();
}
public class SomeClass : IEvent
{
public void Execute()
{
var stackTrace = new StackTrace();
var stackFrames = stackTrace.GetFrames();
var callingMethod = stackFrames[1].GetMethod();
var callingType = callingMethod.DeclaringType;
}
}
public class MyObject : IDisposable
{
public MessageService Service { get; }
public MyObject(MessageService service)
{
Service = service;
}
public void Dispose()
{
Service.Stop();
}
}
public class MessageService
{
public void Start() { }
public void Stop() { }
}
}
I like your question, because it presents an interesting and an unusual situation, but I'm afraid that you won't be able to accomplish your task without going outside of conventional routines that C# has in its arsenal. You may be able to pull something off with unmanaged code, but that's a different topic altogether.
However, aside from it being an interesting question... look at what you're trying to do. You have MyObject, which obviously implements IDisposable and will call Dispose() at the end of that using statement, and you're trying to grab its reference from a different assembly. I don't think this is a good idea.
I suggest revisiting your design and make use of things such as an optional parameter. May not be the "perfect" solution for your situation, as you'll pass it to every Execute in that foreach loop, but it's better than jumping through a thousand fiery hoops of debug API's.

Delegate example what's the point

Like many other posts I've found on SO, I'm trying to get my head around delegates. Hopefully this example is not classed a duplicate because I am asking a specific question about a particular example.
public delegate void HelloFunctionDelegate(string message);
public class Delegate
{
static void Main()
{
HelloFunctionDelegate del = new HelloFunctionDelegate(GoodNight); // delegate will point to the GoodNight method
del("Hello"); // invoke the delegate
}
public static void GoodMorning(string strMessage)
{
Console.WriteLine(strMessage + " and good morning!");
Console.ReadKey();
}
public static void GoodNight(string strMessage)
{
Console.WriteLine(strMessage + " and good night!");
Console.ReadKey();
}
}
So in my example I understand that my delegate is a reference to any function that matches its signature and if I pass in GoodMorning I will see:
Hello and good morning!
and if I pass in GoodNight I will see: Hello and good night!
So its kind of like going through a middle man...
I don't understand is what's the point, why wouldn't I just directly call my GoodMorning / GoodNight methods as and when I need to use them?
Maybe there are better examples for when a delegate is useful, but in this example, why don't I just bypass the middle man?
Since you are asking concretely about this example and not in general: There is no point to doing that in this particular piece of code. It teaches you the mechanics of delegates but it does not teach you the point of using them.
In short, the point is that some piece of code can take a reference to a method without knowing what method it will actually receive. It can later call that delegate at will. That enables more abstractions than otherwise possible.
Consider you have the following delegate:
public delegate void CarEvent(Car car);
And then you have an implementation like the following:
public class Car : DataRecord
{
// An event to execute when the record is deleted
public CarEvent OnDelete { get; set; }
public void Delete()
{
this.DeleteRecord(); // Deletes this record from ex. the database
if (OnDelete)
{
OnDelete(this); // Executes the event
}
}
}
By using a delegate you can subscribe different methods to the OnDelete allowing you to do different things when the record is deleted.
Ex. you can make it so when the record is deleted it's deleted from a "ListView" that holds it.
public class CarList : ListView
{
public CarList()
: base()
{
foreach (var car in CarRecords.LoadCars())
{
var listViewItem = new ListViewItem(car);
car.OnDelete = this.DeleteCarFromList;
this.Items.Add(listViewItem);
}
}
private void DeleteCarFromList(Car deletedCar)
{
this.Items.Remove(deletedCar);
}
}
Of course the above is a rough example and there is a lot more things and different kind of situations where you can use delegates and most notably if you want to use them for events you should consider implementing them using the event keyword. - https://msdn.microsoft.com/en-us/library/awbftdfh.aspx
All in all you want to use delegates when the behavior may differ depending on the overall implementation of something. Like you might want to do one thing in one situation and something else in another situation, but they should both over-all do the same thing.
If you do not need different behaviors based on implementation then there's no need to use delegates. You'd always want to call a method directly if possible.
I hope this explained it okay.

Return a variable of type assigned in parameters?

I'm trying to create a class like Windows Form, which will have multiple new features. It's simply going to be a "better" version of Form, making my work easier on this exact program. Here's what I have so far:
public class SuperForm : Form
{
protected abstract void OnSizeChanged(object sender, EventArgs e);
public SuperForm()
{
this.SizeChanged += OnSizeChanged;
}
}
Not much, it only makes sure every Form will have to define OnSizeChanged which will be called automatically when size changes, but there's going to be more.
What I need next is a method which takes a class/type as it's parameter and initializes a new object of that type, automatically adds it to Controls and then returns the object. Here's an example code (not working) on how I would like it to be like:
public cls NewControl(ClassType cls) // This obviously doesn't work.
// I need it to return an object of type "cls" parameter.
{
cls newControl = new cls();
this.Controls.Add(newControl);
return newControl;
}
I know ClassType is not a valid type, that's why I need help.
And then I could basically call it like this:
Button b = this.NewControl(Button);
Which would return a new button and also add it to this.Controls. I might eventually need to do more of these common tasks when a control is initialized, so that's why I'd like to have it in it's own method.
Is this possible in C#? If not, are there any workarounds? One way would be to define a method for each class inheriting from Control like this:
public Button NewControl(Button b);
public TextBox NewControl(TextBox tb);
public ListBox NewControl(ListBox lb);
But it doesn't seem like a valid option to me.
It sounds like you want to make a generic method, with a couple of constraints on the type parameter:
public T CreateAndAdd<T>() where T : Control, new()
{
T newControl = new T();
Controls.Add(newControl);
return newControl;
}
Here the T : Control constraint makes sure that you're creating a control, so that you'll be able to use Controls.Add. The T : new() constraint makes sure the type argument has a public parameterless constructor, so that you can call new T().
To create a TextBox, for example, you would call the function like this:
var tb = CreateAndAdd<TextBox>()
(I've renamed the method for what I believe to be clarity, btw.)

Firing an event without subscribing to it

I'm currently programming a library for simple games, mostly intended to be used by myself.
Now I've run into a problem. I have a class called "Game" which looks like this:
class Game
{
private List<Entity> entities;
private int counter;
public Game()
{
entities = new List<Entity>();
counter = 0;
}
public AddEntity(Entity entity_)
{
entities.Add(entity_);
// problem! how to inform entity_ that it was added?
counter++;
}
}
Entity is a class which each object that acts in the game must be derived from. Its contents don't really matter. What I am looking for is a way for Game to inform the newly added entity_ class about its owner (current Game instance) and its id (which is what "counter" is for). Now I have been thinking about using an interface which would have a method "OnAdd(Game owner_, int id_)" for that as that would definitely work, but I wanted to make sure there is no preferred way over that. So that is my question:
Is there a better solution for my problem than interfaces? The Entity instance does not know what Game instance it is being added to, and using methods for event-like purposes doesn't feel right in my eyes. I could be wrong if course.
If your Entity has a property of type Game, it's easy to solve this without even using events:
... code ...
entities.Add(entity_);
entity_.AddToGame(this);
... code ...
and then in the AddToGame method, you would do whatever you would do in your event handler, which now is not necessary.
Yes seems correct. But need to add a difference.
Interface - Once changes, you need to track down all implementation.
Abstract Class - Virtual functions can be declared so no need to keep track for the implementations
There are lots of solutions.
You could of course call a method after the .Add:
entity_.HasBeenAdded();
Another solution would be to "reverse the add". Something like:
Entity class:
public Entity
{
...
public void AddTo(IList<Entity> list)
{
if (list == null)
{
throw new ArgumentNullException();
}
list.Add(this);
// Do some logic here, as you now know your object
// has been added.
}
}
...
entity_.AddTo(entities);

Categories