i am new to C# and was wondering if there is a way in C# to call a function based on user input (a string) without a verbose switch statement such as:
switch (u.Action)
{
case "FunctionOne":
FunctionOne(u.Data);
break;
case "FunctionTwo":
FunctionTwo();
break;
etc...
}
while this works fine, once you have a long list of such calls, this code gets a bit unwieldy.
Thanks.........
If your method calls all can accept the same parameters (let's say for the sake of the example one parameter of type Data) you could use a Dictionary<string, Action<Data>>:
Dictionary<string, Action<Data>> callMethodByString = new Dictionary<string, Action<Data>>();
..
You would have to assign the different methods to the dictionary beforehand so you can use them:
callMethodByString.Add("ActionOne", ActionOne);
...
callMethodByString[u.Action](u.Data);
public void ActionOne(Data data)
{
...
}
You can also try using delegates, they are commonly used with events. So, for example if you want to used a method depending on a user input in a textBox, you have to raise an event and then use a delegate. They are just like generic classes or structures, but generic parameters are used only to define the calling convention of the delegate.
Check the documentation in the msdn library
Also check this good example
Take a look at the System.Reflection Namespace.
You can use obj.GetType() or typeof(T) to get the type info of your object. Then GetMethod("SomeMethod") to get the method info and methodInfo.Invoke(...) to invoke the method.
You could do it using Reflection, but doing that would be much simpler if all your methods accepted the same parameters.
Related
I'm trying to write a generic method that will return specific markup when passed an enum. Below is the method which has been reduced to the minimum required code for this question.
public static string GetMarkup(Type enumType)
{
StringBuilder builder = new StringBuilder();
foreach (var val in Enum.GetValues(enumType))
{
builder.Append(val.ToString());
}
return builder.ToString();
}
The method is called like this where CopyType is an enum:
GetDropDownListHtml(typeof(CopyType))
The goal is to be able to call ToString() extension methods I've written for the enums I'll pass into this method. The problem is that to make the method generic, I need to use var to declare my variable in the foreach declaration, but that boxes it. Instead of an enum of CopyType, I have an object that is the boxed CopyType.
In response, I've tried many thinks like this, but to no avail:
((typeof(enumType))val.ToString()
Any ideas?
There's no way to use extension methods to do this to a specific enum. You either need to extend your extension method to support all Enum types, add an is statement in there which you can use to only cast it when necessary, or write a special overload to this function which you call just for this type of enum. This has to do with how extension methods are actually implemented.
The compiler turns an extension method into its static form: myCopyType.ToString() becomes CopyType.ToString(myCopyType) when compiled. But with your scenario (or even with generics) the compiler can't tell what type to use, because the type isn't determined until runtime.
This leaves the three choices above.
In my own code, I went with the first option, based on the code here. You'll be able to call .GetLabel() on any Enum type, and you can put your special labels on this one specifically.
Additionally, you'll need to use foreach (Enum val in ... instead, so as to make sure the compiler knows it's an Enum.
I am using many times on my project functions that need a generic to be passed as a parameter. These functions have different inputs, but they all need a T as parameter.
Let me explain with some code what I am currently doing:
switch (tableName)
{
case "product":
foo<Entities.Product>(value);
break;
case "customer":
foo <Entities.Customer>(value);
break;
}
And this is what I would like to achieve:
foo(MyConverter(tableName), value);
At the begging although not very elegant I thought I could get away with it, but as the code is growing, there are more functions needing this behavior, not only Foo.
Now I have foo2(value1, value2) foo3(value1, value2, value3) and so on.
I am not really good with delegates, I know there must be some way to implement this automatically, but I just can't figure it out.
Any better ideas?
Thanks.
You can try a dictionary that maps string to Action.
So something like:
Dictionary<string, Action<ParamWrapper>> tableActions
= new Dictionary<string, Action<ParamWrapper>>();
tableActions.add("product", foo<Entities.Product>);
tableActions.add("customer", foo<Entities.Customer>);
//to call a function, just do this
tableActions["product"](valueWrapper);
Where foo is defined as
void foo<T>(ParamWrapper paramWrapper) {...}
As far as handling a variety of parameters for foo, you could wrap all the parameters into an object of some new type ParamWrapper. When foo is called, it would extract the parameters from the ParamWrapper.
If you do not know all the table names at compile time, or just want this dynamic, then you would want to use reflection, and add the reflected functions to the dictionary.
I have seen methods passed as parameters in some examples. If I can call one method from another method, why should I pass method as a parameter? What is the purpose behind this design?
Calling one method from another
Passing method as parameter using delegate or Action
Passing in a method as a parameter can be used to prevent dependencies and coupling. Let's take a look at how this can be used for the Strategy pattern:
Let's say we have a method PrintReport, which prints a given list of items, which might be sorted by Name or by Type, based on a parameter. This is the naive approach:
public void PrintReport (List<Item> data, SortOrder sortBy)
{
List<Item> sortedItems;
switch (sortBy)
{
case SortOrder.Name: sortedItems = SortByName(data); break;
case SortOrder.Type: sortedItems = SortByType(data); break;
}
Print(sortedItems);
}
It's simple but it works. But what happens when we want to add a new sort order? We need to update the SortOrder enum, go into PrintReport and add a new case and call the new SortByWhatever method.
But if we passed in a method as a parameter, our PrintReport can be simpler and not care about the sort implementation:
public void PrintReport (List<Item> data, Func<List<Item>, List<Item>> sorter)
{
List<Item> sortedItems = sorter(data);
Print(sortedItems);
}
Now the sorting function can be defined anyway, possibly even in a different assembly that PrintReport isn't even aware of. It can be a lambda function or an anonymous method defined ad-hoc. But in all cases, our method will receive the delegate, use it to sort, and then print the report.
Here's a usage example. At first it looks like we merely moved the switch/case outside of the function, which is important enough since it allows different callers to have different logic. But watch for the third case.
public void HandleData()
{
switch (ReportItemOrder)
{
case SortOrder.Name: PrintReport(data, SortByName); break;
case SortOrder.Type: PrintReport(data, SortByType); break;
case SortOrder.Whatever:
Func<List<Item>, List<Item>> customSort = (items) => /* do something */;
PrintReport(data, customSort);
}
}
Delegates are commonly used to decouple classes and interfaces from each other.
Here's a specific example. Suppose you had a UI class that was responsible for drawing a calendar, but you didn't want it to know exactly how to format the DateTime values into string.
You could define the class something like this:
public sealed class MyCalendarDrawer
{
private readonly Func<DateTime, string> _dateFormatter;
public MyCalendarDrawer(Func<DateTime, string> dateFormatter)
{
_dateFormatter = dateFormatter;
}
public void Draw()
{
// Do some work that involves displaying dates...
DateTime date = DateTime.Now;
string dateString = _dateFormatter(date);
// Display dateString somehow.
}
}
That way, MyCalendarDrawer doesn't need to know how to format the dates - it is told how to do it by being passed a delegate Func<DateTime, string> that it can call to do so.
Treating functions as first class types has its advantages. It gives you functional programming possibilities.
Take the classic case of "Event Handling" for example, you will certainly send a function pointer to another function as a call-back on occurance of an event.
Similarly, here is another hypothetical example
private void CallMeBack(out int type, Func<int> action)
{
type = action();
}
Now I can supply any function to this, like CallMeBack(a, ()=>return 1); and CallMeBack(a, ()=>return 2);
You should read about Delegates.
As example, delegates are useful to define a dynamic callback on a given method completion.
Pseudo-code example:
doSomething(); //your code
updateInterface(continueDoingSomething); //a generic method, passing a delegate
...
doAnythingElse();
updateInterface(continueDoingAnythingElse);
In this example, you could define a generic method "updateInterface" which, as a callback, calls a dynamic method passed in as a delegate.
If not using delegates, you would have to implement two (or more) different methods:
void updateInterfaceAndContinueDoingSomething(){}
void updateInterfaceAndContinueDoingAnythingElse(){}
Truth is, every single example where functions are passed to other functions can be expressed in term of objects implementing a given interface passed to functions.
In other words, there are no obvious reasons delegates are better than interfaces. Upcoming lambdas in Java are an example than you don't really need to be able to pass a function to another function to be able to have a concise syntax.
In yet another words, the ability to pass a function to another function is just a tool in your programmer's toolkit just as passing objectd to functions is. And while this is arguable which is better, one can have a language that doesn't support passing functions to functions at all - Java - and still be able to have the same expressiveness.
Is it in anyway possible ( preferably without using any third party libs), to create a function whose type is determined at runtime in C#?
e.g
public static void myfunc(var x)
{
System.Windows.Forms.MessageBox.Show(x); //just an example
}
NOTE: I want the runtime to determine the type of the parameter and do not want to later cast the parameter to another type, as would be necessary if I use generics. e.g I don't want:
myfunc<T>(T x)
// and then :
MessageBox.Show((string)m);
UPDATE:
I am actually making a function parser for my programming language, which translates to C# code. In my language, I wanted the parameter types to be determined at runtime always. I was looking for some good C# feature for easy translation.
e.g
in my language syntax:
function msg << x
MessageBox.Show x
end
needed to be translated to something that didn't ask for a type at compile time, but would need one at runtime.
e.g
public static void msg(var x)
{
System.Windows.Forms.MessageBox.Show(x);
}
The keyword introduced for runtime binding in C# 4 is dynamic.
public static void myfunc(dynamic x)
This allows you to make assumptions about x that are unchecked at compile time but will fail at runtime if those assumptions prove invalid.
public static void MakeTheDuckQuack(dynamic duck)
{
Console.WriteLine(duck.Quack());
}
The assumption made here is that the parameter will have a method named Quack that accepts no arguments and returns a value that can then be used as the argument to Console.WriteLine. If any of those assumptions are invalid, you will get a runtime failure.
Given classes defined as
class Duck
{
public string Quack()
{
return "Quack!";
}
}
class FakeDuck
{
public string Quack()
{
return "Moo!";
}
}
And method calls
MakeTheDuckQuack(new Duck());
MakeTheDuckQuack(new FakeDuck());
MakeTheDuckQuack(42);
The first two succeed, as runtime binding succeeds, and the third results in an exception, as System.Int32 does not have a method named Quack.
Generally speaking, you would want to avoid this if possible, as you're essentially stipulating that an argument fulfill an interface of some sort without strictly defining it. If you are working in an interop scenario, then perhaps this is what you have to do. If you are working with types that you control, then you would be better served trying to achieve compile time safety via interfaces and/or base classes. You can even use different strategies (such as the Adapter Pattern) to make types you do not control (or cannot change) conform to a given interface.
If you need to know the type... then you need to know the type. You can't have your cake and eat it too.
First off, the cast in your example is unnecessary as all objects implement ToString(). Instead of telling us what you think you need, tell us what problem you are trying to solve. There is almost certainly a solution either via generics or the use of the dynamic keyword (though dynamic is rarely needed), but we need more info. If you add more I'll update this answer.
You could use a type of object or, if you don't know how many items are available, you could use a params object array, i.e. params object[] cParams.
I don’t mean overloading. This might include new Types of classes which I haven’t created yet.
EDIT:
I want to create a method which will return a value of the type it gets as a parameter. I can get a parameter of type object, but I don’t want to return it that way and then cast, I want the return-value itself to be of the same type as the parameter.
You could use reflection:
var returnType = typeof(SomeClass).GetMethod("SomeMethodName").ReturnType;
You can create a generic method which returns a type to be determined. As long as you declare your new classes correctly then they should work.
There are a number of ways of doing this, a search for return generic type c# turns up several different techniques of varying complexity. Fundamentally you have:
public T DoStuff<T>()
{
...
}
however, the "..." is the bit that depends on your application.
Based on your updates, the method you want will be something like:
public T MyMethod<T>(T input)
{
// DoSomething
T result = default(T); // Create your instance of T here
return result;
}
Yes, it's called reflection.
This should answer your question: http://msdn.microsoft.com/en-us/library/system.reflection.methodinfo.returntype.aspx
You can use generic type and generic methods to do that
C# Generic Methods