I'm working with a project for thesis-work for a company and I'm having some difficulties understanding some code.
In their code they have a line like this
_subscriber.StartSubscribing(_messageHandler.HandleMessage);
where _subscriber is function is defined
public override void StartSubscribing(Action<QueueItem> messageHandlerMethod);
And _messageHandler is defined
public void HandleMessage(QueueItem message)
{
//Do code here
}
How come at the top the messageHandler don't need a parameter for HandleMessage?
E.I
_subscriber.StartSubscribing(_messageHandler.HandleMessage(QueueItem));
Because you're not actually executing the method HandleMessage (which would happen if you had parentheses and a parameter). You are passing it as a reference to StartSubscribing which expects a method with a specified signature (void return, one parameter of type QueueItem)
Action<T> is a generic delegate, this particular version is a delegate which specifies no return (void) and a single parameter of type T (or QueueItem in your example)
In fact, it is the method StartSubscribing (or perhaps the class it belongs to) which is likely to provide the instance of QueueItem - perhaps something like this:
public override void StartSubscribing(Action<QueueItem> messageHandlerMethod)
{
// do something to get/create a QueueItem
QueueItem item = SomeMagic();
// pass it back to the passed in delegate
messageHandlerMethod(item);
}
With _subscriber.StartSubscribing(_messageHandler.HandleMessage) you are using a more direct way for _subscriber.StartSubscribing(msg => _messageHandler.HandleMessage(msg)).
So it does need a parameter.
Related
I have a bunch of methods that return List of GridTiles, for example GetTopNeighbour. I would like to be able to pass them to method AutoConnect using the GetNeighboursHandler delegate as a parameter.
public delegate List<GridTile> GetNeighboursHandler(GridTile c);
public List<GridTile> GetTopNeighbour(GridTile c)
{
//do stuff and return list
return null;
}
public GridTile AutoConnect(GridTile c, GetNeighboursHandler del)
{
List<GridTile> tempList = del(c);
// do stuff with the tempList
}
public void Test(GridTile c)
{
AutoConnect(c, GetTopNeighbour(c));
}
In the Test method I get the error: ... cannot convert ...Generic.List...to GetNeighboursHandler.
Have I completely misunderstood how delegates work?
You need to pass a delegate (which is an object that knows how to call the method, ie: it holds the reference of a method)
What you have done is passing the function result that you get after it's execution
GetTopNeighbour(c) returns a List<GridTile>, and you are passing this return value in your code here
AutoConnect(c, GetTopNeighbour(c));
Instead you should pass the reference to that method GetTopNeighbour
AutoConnect(c, GetTopNeighbour);
Refer these This is a tutorial and here's another one
You have to pass the method (or rather, method group) itself, instead of calling it:
AutoConnect(c, GetTopNeighbour);
You're passing the result of GetTopNeighbour(c), which is a List<GridTile>, as a parameter to AutoConnect.
Instead, you want to pass the MethodGroup to be converted to a delegate, like so:
AutoConnect(c, GetTopNeighbour);
I have a method for filtering/searching which now is written for every Windows Form that offers searching. I'm trying to make a generic method in the base class so I can avoid this large amount of repeating code.
Here is the original code which I want to modify:
private void LoadData()
{
GridFilter filter = new GridFilter();
filter.AddRule(dgvColDescription.DataPropertyName, txtDescription.Text);
if (cboColor.SelectedIndex != -1)
{
filter.AddRule(dgvColMaterialColorId.DataPropertyName, cboColor.SelectedValue.ToString());
}
...
//a lot more of this filter.AddRule stuff
...
}
There are two things here I think - the need of instance for GridFilter and the two types of control that I need to use.
Having said that here is my try for a generic method:
protected virtual void AddFilterRules<T>(Control ctrl, String str) where T : GridFilter
{
T filter;
if (ctrl is ComboBox)
{
if ((ctrl as ComboBox).SelectedIndex != -1)
{
filter.AddRule(/*dgvColMaterialColorId.DataPropertyName*/ str, (ctrl as ComboBox).SelectedValue.ToString());
}
}
if (ctrl is TextBox)
{
filter.AddRule(/*dgvColCode.DataPropertyName*/str, ctrl.Text);
}
}
There are some comments because I'm still not sure if I can pass the commented part as string, but the bigger problem for me is the error that I get from the IDE about the filter variable which is:
Use of unassigned local variable "filter"
Is it possible to make a generic method out of it after all and how can I do that?
Add the new() contraint to your method.
protected virtual void AddFilterRules<T>(Control ctrl, String str) where T : GridFilter, new()
and then
T filter = new T();
Either that or pass T in as a parameter:
protected virtual void AddFilterRules<T>(T filter, Control ctrl, String str) where T : GridFilter
Your syntax is correct, but you have two other problems:
You are not initializing T to anything. It is a null reference at the point you are trying to use it. Did you intend to pass in a T?
You're not doing anything with the T. Should you be returning the T? Or assigning it to a property of some other object?
If you pass in a reference to a T and then modify it within the method, then both problems are solved:
protected virtual void AddFilterRules<T>(T filter, Control ctrl, String str)
where T : GridFilter
{
...
}
However in that case your method doesn't need to be generic at all:
protected virtual void AddFilterRules(GridFilter filter, Control ctrl, String str)
{
...
}
Why do you want to use a generic method?
If your filter is always a GridFilter you can just use that type in your method. Even if you use a derived class like SpecialGridFilter this would still work. The fact that in your original method you create a new GridFilter each time means that you can do so in your new method. Hence there is no need for a new method despite the fact that you pass some values to it now.
It looks like you mix up type parameters with ordinary parameters. Having a type parameter doesn't mean you get an instance of that type. It just means you can use the same algorithms for different types without explicitly coding them for each type.
If you really need a generic implementation you can use a type constraint on the generic parameter where T : GridFilter, new(). This allows you to create a new T() in your generic method.
Where will the new method be implemented?
I don't know how GridFilter is implemented now but it looks like AddRule modifies it. If so you shouldn't create a new instance each time because all changes will get lost. AddFilterRules should therefore also be a member of the GridFilter class and each form should have an instance of a GridFilter.
If you cannot change the implementation of GridFilter you can still use an extension method. If it is correct to create a new GridFilter each time you can have an extension method on the Form type. This depends on how GridFilter works.
You should create an instance of T:
T filter = new GridFilter();
If T is always going to be a GridFilter, you may as well replace T by GridFilter:
protected virtual void AddFilterRules<GridFilter>(Control ctrl, String str)
{
GridFilter filter = new GridFilter();
...
}
However, I don't think you should use a generic method at all. You should create a method that returns a GridFilter:
protected virtual GridFilter AddFilterRules(Control ctrl, String str)
{
GridFilter filter = new GridFilter();
...
return filter;
}
This has a game development project under itself, but it's really about coding and mapping data to other pieces of data. This is why I decided to post it here.
The format that I'm using for external inventory item data storage:
[ID:IT_FO_TROUT]
[Name:Trout]
[Description:A raw trout.]
[Value:10]
[3DModel:null]
[InventoryIcon:trout]
[Tag:Consumable]
[Tag:Food]
[Tag:Stackable]
[OnConsume:RestoreHealth(15)]
[OnConsume:RestoreFatigue(15)]
The question is concentrated upon the last 2 OnConsume properties. Basically, the two properties mean that when the item gets consumed, the consumer's health goes up by 15 points, and his fatigue does so as well. This, in the background, invokes 2 different methods:
void RestoreHealth(Character Subject, int Amount);
void RestoreFatigue(Character Subject, int Amount);
How would you go about mapping the methods to their in-file string counterparts? This is what I thought of:
Every time an item gets consumed, a list of strings (the events) gets passed to an Item event manager. The manager parses each string and calls the appropriate methods. Very easy to set up, and since this is not an operation that happens too often, the impact on performance might not be considerable (strings will also be tiny (max 10-15 characters) in size, and parsed in O(n) time).
Each inventory item (class) parses the string events once and only once, on initialization. Each string event gets mapped to its appropriate method via a dictionary. This is the most efficient method in terms of performance that I can think of, but it makes it extremely difficult to do other things:
All of the values in the dictionary would have to be delegates of the same kind. This means I cannot keep
a) RestoreHealth(int)
b) SummonMonster(Position, Count)
in the same dictionary, and would have to set a new data structure for each kind of callable method. This is a tremendous amount of work to do.
Some ways that came to mind, to improve both methods:
I could use some sort of temporary cache inside the Item event
manager, so that an item's OnConsume events don't get parsed
twice? I might hit the same issues as the ones I hit during 2)
though, as the cache would have to be a map<InventoryItem,List<delegate>>.
The hashtable data structure inside the .NET libraries allows
for any kind of object to be a key and/or value at any given time
(unlike the dictionary). I could use this and map string A to
delegate X, while also having mapped string B to delegate Y
inside the same structure. Any reasons why I should not do this? Can
you foresee any trouble that would be brought by this method?
I was also thinking about something in the ways of reflection, but I'm not exactly experienced when it comes to it. And I'm pretty sure parsing the string every time is faster.
EDIT
My final solution, with Alexey Raga's answer in mind. Using interfaces for each kind of event.
public interface IConsumeEvent
{
void ApplyConsumeEffects(BaseCharacter Consumer);
}
Sample implementer (particular event):
public class RestoreHealthEvent : IConsumeEvent
{
private int Amount = Amount;
public RestoreHealthEvent(int Amount)
{
this.Amount = Amount;
}
public void ApplyConsumeEffects(BaseCharacter Consumer)
{
Consumer.Stats.AlterStat(CharacterStats.CharStat.Health, Amount);
}
}
Inside the parser (the only place where we care about the event's particularities - because we're parsing the data files themselves):
RestoreHealthEvent ResHealthEv = new RestoreHealthEvent (Value);
NewItem.ConsumeEvents.Add (ResHealthEv );
When a character consumes an item:
foreach (IConsumeEvent ConsumeEvent in Item.ConsumeEvents)
{
//We're inside a parent method that's inside a parent BaseCharacter class; we're consuming an item right now.
ConsumeEvent.ApplyConsumeEffects(this);
}
Why not "map" them to "command" classes once-and-only-once instead?
For example,
[OnConsume:RestoreHealth(15)]
[OnConsume:RestoreFatigue(15)]
could be mapped to RestoreHealth and RestoreFatigue command classes that can be defined as:
public sealed class RestoreHealth : ICommand {
public int Value { get; set; }
//whatever else you need
}
public sealed class SummonMonster : ICommand {
public int Count {get; set; }
public Position Position { get; set; }
}
Consider commands as just wrappers for your parameters at this point ;) So instead of passing multiple parameters you always wrap them and pass only one.
It also gives a bit of semantics too.
Now you can map your inventory items to commands that need to be "sent" when each item is consumed.
You can implement a simple "bus" interface like:
public interface IBus {
void Send(ICommand command);
void Subscribe(object subscriber);
}
and now you just get an instance of IBus and call its Send method when appropriate.
By doing this you separate your "definition" (what needs to be done) and your logic (how to perform an action) concerns.
For the receiving and reacting part you implement the Subscribe method to interrogate the subscriber instance (again, once and only once) figuring out all its method which can "handle" commands.
You can come up with some IHandle<T> where T: ICommand interface in your handlers, or just find them by convention (any Handle method that accepts only one argument of ICommand and returns void), or whatever works for you.
It is basically the same part of "delegate/action" lists that you were talking about except that now it is per command:
map<CommandType, List<action>>
Because all the actions now accept only one parameter (which is ICommand) you can easily keep them all in the same list.
When some command is received, your IBus implementation just gets the list of actions for the given command type and simply calls these actions passing the given command as a parameter.
Hope it helps.
Advanced: you can do one step further: have a ConsumeItem command:
public sealed void ConsumeItem: ICommand {
public InventoryItem Item { get; set; }
}
You already have a class that is responsible for holding a map between InventoryItem and Commands, so this class can become a process manager:
It subscribes to ConsumeItem command (through the bus)
In its Handle method it gets the list of commands for the given inventory item
It sends these commands to the bus.
Well, now we have separated clearly these three concerns:
While consuming an inventory item we just "know" about IBus and send a ConsumeItem command and we don't care what happens next.
The "ConsumeInventoryManager" (whatever you call it) also knows about IBus', subscribes forConsumeItem` command and "knows" what needs to be done when each item is consumed (list of commands). It just sends these commands and doesn't care who and how handle them.
The business logic (characters, monsters, etc) just handle the commands that make sense to them (RestoreHealth, Die, etc) and don't care where (and why) they came from.
Good luck :)
My advice is to use reflection, that is define a method that invokes the desired method based on the specified name. Here's a working example:
class Program
{
static void Main(string[] args)
{
SomeClass someInstance = new SomeClass();
string name = Console.ReadLine();
someInstance.Call("SayHello", name);
}
}
class SomeClass
{
public void SayHello(string name)
{
Console.WriteLine(String.Format("Hello, {0}!", name));
}
public void Call(string methodName, params object[] args)
{
this.GetType().GetMethod(methodName).Invoke(this, args);
}
}
You can do it this way provided the following conditions hold:
You are absolutely sure that a call is possible, that is a method of the specified name exists and the number and types of parameters are correct
The method of the specified name is not overloaded, otherwise You'll get a System.Reflection.AmbiguousMatchException
There exists a superclass from which all of the classes You want to use the Call method on derive; You should define this method in that class
To assure* that conditions 1. and 2. are satisfied You could use a more specific version of Type.GetMethod which takes into account not only the name of the method, but also the number and types of the parameters, and check that there is such a method before invoking it; then the Call method would look like this (*it won't work for methods with parameters marked as out or ref):
public void Call(string methodName, params object[] args)
{
//get the method with the specified name and parameter list
Type[] argTypes = args.Select(arg => arg.GetType()).ToArray();
MethodInfo method = this.GetType().GetMethod(methodName, argTypes);
//check if the method exists and invoke it
if (method != null)
method.Invoke(this, args);
}
REMARK: MethodInfo.Invoke method actually returns an object, so You could define the Call method to return some value by specifying the return type and using the return keyword together with an appropriate cast or some other method of converting the result to the desired type, if it's possible - remember to check if it is.
If condition 3. isn't satisfied, I'd go with writing an extension method. Here's an example of an extension method that returns a generic value, which I think should be sufficient in most cases (again, it won't work with ref or out) and should work on almost every object possible in the .NET Framework (I'd be grateful for pointing out a counterexample):
public static class Extensions
{
//invoke a method with the specified name and parameter list
// and return a result of type T
public static T Call<T>(this object subject, string methodName, params object[] args)
{
//get the method with the specified name and parameter list
Type[] argTypes = args.Select(arg => arg.GetType()).ToArray();
MethodInfo method = subject.GetType().GetMethod(methodName, argTypes);
//check if the method exists
if (method == null)
return default(T); //or throw an exception
//invoke the method and get the result
object result = method.Invoke(subject, args);
//check if something was returned
if (result == null)
return default(T); //or throw an exception
//check if the result is of the expected type (or derives from it)
if (result.GetType().Equals(typeof(T)) || result.GetType().IsSubclassOf(typeof(T)))
return (T)result;
else
return default(T); //or throw an exception
}
//invoke a void method more conveniently
public static void Call(this object subject, string methodName, params object[] args)
{
//invoke Call<object> method and ignore the result
subject.Call<object>(methodName, args);
}
}
You should then be able to use, for example, someObject.Call<string>("ToString") instead of someObject.ToString(). Finally, at this point I'd strongly recommend:
Use more specific type than object if possible
Use some more sophisticated and unique name than Call - it may get obscured in case some class has a method with the same signature defined
Lookup covariance and contravariance to get more useful knowledge
I have the following C# class:
public class MyType<T>
{
public void TryParse(string p_value)
{
T value ;
Parser.TryParse(p_value, out value);
// Do something with value
}
}
The point is to call the right Parser.TryParse method, depending on the generic type T.
This uses the following static class:
static public class Parser
{
static public void TryParse(string p_intput, out object p_output)
{
// Do something and return the right value
}
static public void TryParse(string p_intput, out double p_output)
{
// Do something and return the right value
}
static public void TryParse(string p_intput, out int p_output)
{
// Do something and return the right value
}
}
I expected this to work: In the worst case, the "object" TryParse would be called. Instead, I have two compilation errors:
CS1502: The best overloaded method match for 'Parser.TryParse(string, out object)' has some invalid arguments
CS1503: Argument 2: cannot convert from 'out T' to 'out object'
Question 1: I don't understand why this doesn't work: I can be naive, but aren't all C# objects supposed to derive from "object" ? Why T cannot be converted to object?
Question 2: How can I dispatch a method with generic type T into the right non-generic methods (i.e. MyType<T>.TryParse calling the right Parser.TryParse according to the right type of T) ?
Note
The question was edited to reflect the original question intent (as written in the title: How to dispatch C# generic method call into specialized method calls)
Actually, ref and out parameters do not allow type variation. So, to pass a variable to a method expecting an out object parameter, that variable must be declared as object.
From the specification (§10.6.1.2 and §10.6.1.3)
When a formal parameter is a reference parameter, the corresponding argument in a method invocation must consist of the keyword ref followed by a variable-reference (§5.3.3) of the same type as the formal parameter.
When a formal parameter is an output parameter, the corresponding argument in a method invocation must consist of the keyword out followed by a variable-reference (§5.3.3) of the same type as the formal parameter.
See: Why do ref and out parameters not allow type variation? for some insight into why.
Bonus question: How can I dispatch a method with generic type T into the right non-generic methods (i.e. MyType<T>.TryParse calling the right Parser.TryParse according to the right type of T)?
I'm going to turn it back around on you. Why are you doing this? If you are invoking MyType<T>.TryParse as, say, MyType<int>.TryParse, why not call Int32.TryParse directly? What is this extra layer buying you?
I know this is somewhat low-tech, but I have had the same problem, where I solved it by making a Dictionary<Type, Parser> containing the individual parsers. I will be interested in what answers this questions bring.
Regards,
Morten
Current solution
The current solution I use at work is based on dynamic dispatch, that is, the keyword dynamic as defined on C# 4.0.
The code is something like (from memory) :
public class Parser
{
static public void TryParse<T>(string p_input, out T p_output)
{
// Because m_p is dynamic, the function to be called will
// be resolved at runtime, after T is known...
m_p.DoTryParse(p_input, out p_output) ;
}
// The dynamic keyword means every function called through
// m_p will be resolved at runtime, at the moment of the call
private dynamic m_p = new Parser() ;
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
private void DoTryParse(string p_input, out double p_output)
{ /* Do something and return the right value */ }
private void DoTryParse(string p_input, out int p_output)
{ /* Do something and return the right value */ }
// etc.
private void DoTryParse<T>(string p_input, out T p_output)
{
// fallback method... There are no dedicated method for T,
// so p_output becomes the default value for T
p_output = default(T) ;
}
}
The elegant part is that it can't fail (the fallback function will be called, if none with a better signature match is found), and that it follows a simple pattern (overload the function).
Of course, the real-life, production code is somewhat different, and more complicated because, with but one public static method, I want to :
parse both reference objects (classes) and value objects (structs)
parse enums
parse nullable types
I want to offer the user the possibility to derive from Parser to offer its own overloads in addition to the default ones
But I guess the use of dynamic in the current solution is, in the end, the same thing as doing reflection as done in the original answer below. Only the "notation" changes.
Conclusion, I now have the following method :
public class Parser
{
static public void TryParse<T>(string p_input, out T p_output)
{
// etc.
}
}
which is able to parse anything, including in situations where T is not known at compile time (because the code is generic).
Original answer
Jason's answer was right about the first question (about the compiler errors). Still, I had no solution to my problem (dispatching from a generic method to non-generic methods according to the runtime generic type T).
I tried LukeH's answer, but it didn't work: The generic method is always called, no matter what (even when removing the out qualifier of the second parameter).
Morten's answer is the most sane one that should works, but it doesn't make use of reflection.
So, to solve my own problem, I used reflection. This needs the rewriting of the generic TryParse method:
public class MyType<T>
{
public void TryParse(string p_value)
{
T value = default(T);
// search for the method using reflection
System.Reflection.MethodInfo methodInfo = typeof(Parser).GetMethod
(
"TryParse",
new System.Type[] { typeof(string), typeof(T).MakeByRefType() }
);
if (methodInfo != null)
{
// the method does exist, so we can now call it
var parameters = new object[] { p_value, value };
methodInfo.Invoke(null, parameters);
value = (T)parameters[1];
}
else
{
// The method does not exist. Handle that case
}
}
}
I have the source code available if needed.
This problem intrigued me, so I did some research and found a nice thing by Paul Madox. This seems to do the trick.
public static T SafeParseAndAssign<T>(string val) where T: new()
{
try
{
T ValOut = new T();
MethodInfo MI = ValOut.GetType().
GetMethod("Parse", new Type[] { val.GetType() });
return (T)MI.Invoke(ValOut, new object[] { val });
}
catch
{
// swallow exception
}
return default(T);
}
I want to have a library that will have a function in it that accepts an object for it's parameter.
With this object I want to be able to call a specified function when X is finished. The function that will be called is to be specified by the caller, and X will be done and monitored by the library.
How can I do this?
For reference I'm using C# and .NET 3.5
Two options for you:
Have the function accept a delegate (Action for a callback that doesn't return anything, Func for one that does) and use an anonymous delegate or Lambda Expression when calling it.
Use an interface
Using a delegate/lambda
public static void DoWork(Action processAction)
{
// do work
if (processAction != null)
processAction();
}
public static void Main()
{
// using anonymous delegate
DoWork(delegate() { Console.WriteLine("Completed"); });
// using Lambda
DoWork(() => Console.WriteLine("Completed"));
}
If your callback needs to have something passed to it, you can use a type parameter on Action:
public static void DoWork(Action<string> processAction)
{
// do work
if (processAction != null)
processAction("this is the string");
}
public static void Main()
{
// using anonymous delegate
DoWork(delegate(string str) { Console.WriteLine(str); });
// using Lambda
DoWork((str) => Console.WriteLine(str));
}
If it needs multiple arguments, you can add more type parameters to Action. If you need a return type, as mentioned use Func and make the return type the last type parameter (Func<string, int> is a function accepting a string and returning an int.)
More about delegates here.
Using an interface
public interface IObjectWithX
{
void X();
}
public class MyObjectWithX : IObjectWithX
{
public void X()
{
// do something
}
}
public class ActionClass
{
public static void DoWork(IObjectWithX handlerObject)
{
// do work
handlerObject.X();
}
}
public static void Main()
{
var obj = new MyObjectWithX()
ActionClass.DoWork(obj);
}
Sounds like a perfect recipe for delegates - in particular, callbacks with delegates are exactly how this is handled in the asynchronous pattern in .NET.
The caller would usually pass you some state and a delegate, and you store both of them in whatever context you've got, then call the delegate passing it the state and whatever result you might have.
You could either make the state just object or potentially use a generic delegate and take state of the appropriate type, e.g.
public delegate void Callback<T>(T state, OperationResult result)
Then:
public void DoSomeOperation(int otherParameterForWhateverReason,
Callback<T> callback, T state)
As you're using .NET 3.5 you might want to use the existing Func<...> and Action<...>
delegate types, but you may find it makes it clearer to declare your own. (The name may make it clearer what you're using it for.)
The object in question will need to implement an interface provided by you. Take the interface as a parameter, and then you can call any method that the interface exposes. Otherwise you have no way of knowing what the object is capable of. That, or you could take a delegate as a parameter and call that.
Is there a reason not to have your library provide a public event to be fired when the operation is complete? Then the caller could just register to handle the event and you don't have to worry about passing around objects or delegates.
The object implementing an interface you have provided would work, but it seems to be more the Java approach than the .NET approach. Events seem a bit cleaner to me.
You can use System.Action available in C#.NET for callback functions. Please check this sample example:
//Say you are calling some FUNC1 that has the tight while loop and you need to
//get updates on what percentage the updates have been done.
private void ExecuteUpdates()
{
Func1(Info => { lblUpdInfo.Text = Info; });
}
//Now Func1 would keep calling back the Action specified in the argument
//This System.Action can be returned for any type by passing the Type as the template.
//This example is returning string.
private void Func1(System.Action<string> UpdateInfo)
{
int nCount = 0;
while (nCount < 100)
{
nCount++;
if (UpdateInfo != null) UpdateInfo("Counter: " + nCount.ToString());
//System.Threading.Thread.Sleep(1000);
}
}