public static void WaitUntilElementVisible(Action<string> preAction = null)
{
preAction?.Invoke();
}
static void Main(string[] args)
{
WaitUntilElementVisible((str) => PanelHandler("in"));
}
public static void PanelHandler(string className)
{
// do something
}
I want to execute PanelHandler("in") if its not null inside the WaitUntilElementVisible() method. However the Invoke() expects a string. But the strange thing is that I'm already giving it a string when I do WaitUntilElementVisible(() => PanelHandler("in")); how can I make Invoke use the string which I pass via lambda?
I want to call WaitUntilElementVisible() in such a way that WaitUntilElementVisible() will invoke PanelHandler with "in".
Your WaitUntilElementVisible is using an Action<string> delegate which is simply a reference to a method that expects a string argument but it does not know anything about the concrete method you want to call, in your example, the reference being used is the anonymous method you create with your lambda expression (str) =>, then, that method calls your actual method but you have already passed the reference of the original method!
If you convert the anonymous method to a regular one it is easier to understand what is happening:
static void Main(string[] args)
{
WaitUntilElementVisible(MyActionMethod);
}
public static void WaitUntilElementVisible(Action<string> preAction = null)
{
preAction?.Invoke();
}
public static void MyActionMethod(string str)
{
PanelHandler("in");
}
public static void PanelHandler(string className)
{
Console.WriteLine(className);
}
As you can see the reference you are passing is to MyActionMethod and not to PanelHandler and the str parameter is not used at all.
So you need to add a string argument to your method to pass the value and then you have the reference to the method and the value you need to pass:
static void Main(string[] args)
{
WaitUntilElementVisible(PanelHandler, "in");
}
public static void WaitUntilElementVisible(Action<string> preAction = null, string value = null)
{
preAction?.Invoke(value);
}
public static void PanelHandler(string className)
{
Console.WriteLine(className);
}
Or you can remove the string requirement and simply accept any method and then your code will work:
static void Main(string[] args)
{
WaitUntilElementVisible(() => PanelHandler("in"));
}
public static void WaitUntilElementVisible(Action preAction = null)
{
preAction?.Invoke();
}
public static void PanelHandler(string className)
{
Console.WriteLine(className);
}
Now of course, you are simply telling the compiler to invoke whichever method is referenced by your action delegate.
Another option is to use a dynamically typed language such as Python ;-)
def waitUntilElementVisible(preAction = None):
if preAction is not None:
preAction()
def panelHandler(className):
print(className)
if __name__=='__main__':
waitUntilElementVisible(panelHandler('in'))
In this case this will work because references are resolved at run-time and not at compile time like in .NET.
The problem is due to your declaration of WaitUntilElementVisible, the declaration
public static void WaitUntilElementVisible(Action<string> preAction = null)
declares a delegate that will take a string parameter, that is, it is expecting that the call to WaitUntilElementVisible will look like:
WaitUntilElementVisible(someString => PanelHandler(someString));
Which would be the useful in the situation where the WaitUntilElementVisible was to provide the string to your delegate.
What you want is for the declaration of WaitUntilElementVisible to be
public static void WaitUntilElementVisible(Action preAction = null)
Which means that it expects a delegate that takes no arguments.
Related
I am trying to call the method PrintBanner from main. However, it won't let me.
static void Main(string[] args)
{
string banner;
banner = PrintBanner("This is whats supposed to be printed.");
}
public static void PrintBanner()
{
return PrintBanner(banner);
}
I need the message to be called from main. But the error says that no overload for PrintBanner takes one argument. And that the name banner does not exist in PrintBanner.
Am I supposed to put string banner in PrintBanner method?
I'm unclear on what you are trying to accomplish here. Though it seems by your code that you want to both print and assign a value at with the PrintBanner method.
public static void Main(string[] args)
{
string banner;
banner = PrintBanner("This is whats supposed to be printed.");
}
public static string PrintBanner(string text)
{
Console.Write(text);
return text;
}
Or maybe you don't want the method itself to perform the assignment?:
public static void Main(string[] args)
{
string banner;
PrintBanner(banner = "This is whats supposed to be printed.");
}
public static void PrintBanner(string text)
{
// The text variable contains "This is whats supposed to be printed." now.
// You can perform whatever operations you want with it within this scope,
// but it won't alter the text the banner variable contains.
}
If not, then please try to elaborate further on your goal.
Oh boy... first off, your PrintBanner() method is void, therefore you won't be able to "return" anything.
Also, because your PrintBanner doesn't take any parameters, you can't pass any arguments to it.
Try this:
static void Main(string[] args)
{
string banner = PrintBanner("This is what's supposed to be printed.")
Console.WriteLine(banner);
Console.ReadLine();
}
//PrintBanner now has a string parameter named message (you can name it
//whatever you want, but in the method in order to access that parameter, the
//names have to match), thus when we call it in main, we can pass a string as
//an argument
public static string PrintBanner(string message)
{
return message;
}
I just need to know if there's a smart way to detect if a particular Type method has overloads or not.
At the moment I'm iterating through methods and searching for DeclaringType+Name ambiguity...but I think it's a bit lame :)
The overload is what happens when you have two methods with the same name but different signatures.
So if we can the method is override by check method name whether more than one.
I would create an extension method IsOverloads to make it.
use the IsOverloads method need to provide at least two parameter
the class Type.
check method name
Using reflection to gets method information from the class, then check the method name greater than one means the method is overload.
public static class Ext {
public static bool IsOverloads(this Type type,string methodName)
{
return IsOverloads(type, methodName, BindingFlags.Public | BindingFlags.Instance);
}
public static bool IsOverloads(this Type type,
string methodName,
BindingFlags flags)
{
var info = type.GetMethods(flags);
return info.Where(o1 => o1.Name == methodName).Count() > 1;
}
}
Here is a simple
public class Program
{
public void Test() { }
public void Test(int a) { }
public void TestNo(int a) { }
public static void Main()
{
Console.WriteLine(typeof(Program).IsOverloads("Test")); //True
Console.WriteLine(typeof(Program).IsOverloads("TestNo")); //false
}
}
c# online
I'm working with an C API in C#. In C Methods are passed as parameters and I'm trying to accomplish the same thing in C#.
in C I would call the functions the following way:
LL_SetStatusCb(OnStatusRcv);
LL_SetScanCb(scanCb);
LL_Scan();
Note that the used methods are defined in the following way:
void OnStatusRcv(ll_status_t status)
void scanCb(ll_scan_result_t *result)
In C# the methods are defined in the same way but I don't know how I can pass those methods.
C# equivalent of function pointers are delegates. You can use Func and Action to pass methods as parameters. Func delegate represents method which takes N arguments and returns value, Action delegate represents void method.
Consider this
void (* myFunction)(int parameter)
in C# would be
Action<int>
Please try this code:
create ll_scan_result_t and ll_status_t classes.
class Program
{
delegate void ActionRef<T>(ref T item);
static void Main(string[] args)
{
ll_status_t _status = new ll_status_t();
LL_SetStatusCb(_status, OnStatusRcv);
ll_scan_result_t _scan = new ll_scan_result_t();
LL_SetScanCb(ref _scan);
}
static void LL_SetScanCb(ref ll_scan_result_t status, ActionRef<ll_scan_result_t> getCachedValue)
{
//... do something
}
static void LL_SetStatusCb(ll_status_t result, Action<ll_status_t> getCachedValue)
{
//... do something
}
static void OnStatusRcv(ref ll_scan_result_t sresult)
{
//... do something
}
static void scanCb(ll_status_t s)
{
//... do something
}
}
Use the Func Delegate like below
public class myClass
{
public bool TestMethod(string input)
{
return true;
}
public bool Method1(Func<string, bool> methodName)
{
return true;
}
public void newMthod()
{
Method1(TestMethod);
}
}
In C#, the equivalent to C/C++ function pointers are delegates. A delegate is a type that represents references to methods with a particular parameter list and return type. When you instantiate a delegate, you can associate its instance with any method that has a compatible signature and return type. You can call the method through the delegate instance.
Here's an example. First, declare a delegate:
public delegate void Del(string message);
Now, Del is a delegate type which can be used to call to any method that returns void and accepts an argument of type string. Now, let's create some method matching the signature and return type of Del:
public static void DelegateMethod(string message)
{
Console.WriteLine(message);
}
Now, let's create an instance of Del and associate it with DelegateMethod, like this:
Del handler = DelegateMethod;
If you want to call DelegateMethod, you can do it by:
handler("Hello World");
Notice that since Del is a type, you can do something like this:
public static void SomeMethod(Del callback, string callbackParams)
{
callback(callbackParams);
}
Which can be used as:
SomeMethod(handler, "Hello World");
With that said, there are othes ways of working with delegates. You can use Func and Action delegates. Func is a delegate that points to a method that accepts one or more arguments and returns a value, that is, it doesn't return void. Action is a delegate that points to a method which in turn accepts one or more arguments but returns no value (returns void). In other words, you should use Action when your delegate points to a method that returns void.
Here's an example of using an Action delegate:
static void Main(string[] args)
{
Action<string> action = new Action<string>(Display);
action("Hello!!!");
Console.Read(); //Prevents from closing the command line right away.
}
static void Display(string message)
{
Console.WriteLine(message);
}
Therefore, something like
void (* funcPtr)(int) = &someFuncWithAnIntArg;
(*funcPtr)(10);
Is equivalent in C# to
Action<int> funcPtr = new Action<int>(someFuncWithAnIntArg);
funcPtr(10);
And now for a Func delegate:
static void Main(string[] args)
{
Func<int, double> func = new Func<int, double>(CalculateHra);
Console.WriteLine(func(50000));
Console.Read();
}
static double CalculateHra(int basic)
{
return (double)(basic * .4);
}
The syntax for a Func delegate accepting an argument and returning a value is like this Func<TArgument, TOutput> where TArgument is the type of the argument and TOutput is the type of returned value. There are many more types of Func (browse the left tree index) and Action (also browse the left tree index) delegates.
And last, but not least, we have the Predicate delegates which is typically used to search items in a collection or a set of data. Let's define some boilerplate code to explain:
class Customer
{
public int Id { get; set; }
public string FirstName { get; set; }
}
Then, let's try it in:
static void Main(string[] args)
{
List<Customer> customers = new List<Customer>();
customers.Add(new Customer { Id = 1, FirstName = "Stack" });
customers.Add(new Customer { Id = 2, FirstName = "Overflow" });
Predicate<Customer> pred = x => x.Id == 1;
Customer customer = customers.Find(pred);
Console.WriteLine(customer.FirstName);
Console.Read();
}
The last code snippet will print "Stack". What happened is that the Predicate delegate named prep was used as a search criteria to search in the list customers. Basically, this delegate was run on every element x of the list, and when x.Id == 1 it returns true, false otherwise. The x element where the predicate returned true is returned as the result of the Find method.
I want to write a method that will analyze custom attributes of any method (with any number of arguments and any return type) knowing only method info.
This function will check if method has specific Attribute. like this: var tmp = methodInfo.GetCustomAttributes(typeof(LineItemAttribute),false); and if it has such attribute It will execute it.And I want to make call of that function really easy to use. So, in example there are three methods and method GetMethodAttributes that I want to call.
class Test
{
public static void Main()
{
}
public void Test1(){}
public void Test2(int a){}
public void Test3(object a, string c, Boolean d);
public void GetMethodAttributes(MethodInfo mi) {}
}
Ideally I want to write something like that
public static void Main()
{
var t = new Test();
GetMethodAttributes(t.Test1);
GetMethodAttributes(t.Test2);
GetMethodAttributes(t.Test3);
}
I don't want to use string representation of the method names as method names may change, like that:
MethodInfo info = type.GetMethod(name);
Do I have any options? Basically I need a way to use delegates for functions with different sinatures
As Chris Sinclair pointed out in the comment above; you can use a delegate without using reflection or expression trees to get the MethodInfo. The downside is that the compiler is not able to infer the generic parameter so you have to specify the delegate type to match the signature of the given method like this:
public class Test
{
public static void Main()
{
var t = new Test();
CheckMethodAttributes<Action>(t.Test1);
CheckMethodAttributes<Action<int>>(t.Test2);
CheckMethodAttributes<Action<object, string, bool>>(t.Test3);
}
public void Test1() { }
public void Test2(int a) { }
public void Test3(object a, string c, bool d) { }
public static void CheckMethodAttributes<T>(T func)
{
MethodInfo method = new MethodOf<T>(func);
// Example attribute check:
var ignoreAttribute = method.GetAttribute<IgnoreAttribute>();
if (ignoreAttribute != null)
{
// Do something here...
}
}
}
This uses two utility classes, the MethodOf<T> for extracting the MethodInfo from the given Delegate and some AttributeUtils to get strongly typed custom attribute retrieval:
public static class AttributeUtils
{
public static bool HasAttribute<TAttribute>(this MemberInfo member, bool inherit = true)
where TAttribute : Attribute
{
return member.IsDefined(typeof(TAttribute), inherit);
}
public static TAttribute GetAttribute<TAttribute>(this MemberInfo member, bool inherit = true)
where TAttribute : Attribute
{
return member.GetAttributes<TAttribute>(inherit).FirstOrDefault();
}
public static IEnumerable<TAttribute> GetAttributes<TAttribute>(this MemberInfo member, bool inherit = true)
where TAttribute : Attribute
{
return member.GetCustomAttributes(typeof(TAttribute), inherit).Cast<TAttribute>();
}
}
public class MethodOf<T>
{
public MethodOf(T func)
{
var del = func as Delegate;
if (del == null) throw new ArgumentException("Cannot convert func to Delegate.", "func");
Method = del.Method;
}
private MethodInfo Method { get; set; }
public static implicit operator MethodOf<T>(T func)
{
return new MethodOf<T>(func);
}
public static implicit operator MethodInfo(MethodOf<T> methodOf)
{
return methodOf.Method;
}
}
You can do something like this using Expression Trees, where you pass the method via a lambda expression. You do still need to pass stub values for the parameters, however. For a good example of this in action, check out the source code for Moq, which uses this pattern extensively for setting up mock behaviors for unit testing. Just note that this is not a trivial thing to set up. If you need something relatively quick and dirty, your best bet is probably string names with a good refactoring tool and/or automated tests to help deal with the renaming issues.
public static void SendEmail(String from, String To, String Subject, String HTML, String AttachmentPath = null, String AttachmentName = null, MediaTypeNames AttachmentType = null)
{
....
// Add an attachment if required
if (AttachmentPath != null)
{
var ct = new ContentType(MediaTypeNames.Text.Plain);
using (var a = new Attachment(AttachmentPath, ct)
{
Name = AttachmentName,
NameEncoding = Encoding.UTF8,
TransferEncoding = TransferEncoding.Base64
})
{
mailMessage.Attachments.Add(a);
}
}
....
}
As you can see the MediaTypeNames AttachmentType throws the error:
'System.Net.Mime.MediaTypeNames': static types cannot be used as parameters
What is the best way to deal with this?
You can't pass a static type to a method as a parameter because then it would have to be instantiated, and you can't create an instance of a static class.
It's not recommended but you can simulate use of Static classes as parameters.
Create an Instance class like this :
public class Instance
{
public Type StaticObject { get; private set; }
public Instance(Type staticType)
{
StaticObject = staticType;
}
public object Call(string name, params object[] parameters)
{
MethodInfo method = StaticObject.GetMethod(name);
return method.Invoke(StaticObject, parameters);
}
public object Call(string name)
{
return Call(name, null);
}
}
Then your function where you would use the static class :
private static void YourFunction(Instance instance)
{
instance.Call("TheNameOfMethodToCall", null);
}
For instance.Call :
The first parameter is the name of the method of your static class to call
The second parameter is the list of arguments to pass to the method.
And use like this :
static void Main(string[] args)
{
YourFunction(new Instance(typeof(YourStaticClass)));
Console.ReadKey();
}
The best deal is definitely to remove the last parameter. Since type is static you don't need a reference to an instance and you can refer to its members from your function body.
Use a different type for the argument.
A method argument needs to be of a type that can accept a reference to an instance, so it can't be a static class.
You can wrap static types around an interface or another non-static class and add that as the parameter. Not ideal but a way around it. Or simply just reference the static type in the method body itself.
Send a static class as the type of the parameter
and then give it a variable name for use in the function.
This works because the new variable is a reference to the static class.
It is necessary to address the global variable problem.
If you use a static class as a variable inside a method,
you need to pass it in as a parameter, to avoid the global variable issue.
This is basic structured programming 101 from the 80's.
It doesn't look like you even use that parameter in your method. You should just remove it because MediaTypeNames cannot be instantiated anyway.
A workaround to passing static parameters is to pass it as an object.
Function:
public static void HoldKey(object key)
{
...
}
Call function:
Function(static param);