C# function uses extension function but VB equivalent does not? - c#

So I have the following code in C#:
public Container ConfigureSimpleInjector(IAppBuilder app)
{
var container = new Container();
container.Options.DefaultScopedLifestyle = new AsyncScopedLifestyle();
container.RegisterPackages();
app.Use(async (context, next) =>
{
using (AsyncScopedLifestyle.BeginScope(container))
{
await next();
}
});
container.Verify();
return container;
}
The app.Use() is defined as Owin.AppBuilderUserExtensions.Use() and looks like this:
public static IAppBuilder Use(this IAppBuilder app, Func<IOwinContext, Func<Task>, Task> handler);
The VB equivalent is as follows:
Public Function ConfigureSimpleInjector(app As IAppBuilder) As Container
Dim container = New Container()
container.Options.DefaultScopedLifestyle = New AsyncScopedLifestyle()
container.RegisterPackages()
app.Use(Async Sub(context, [next])
Using AsyncScopedLifestyle.BeginScope(container)
Await [next]()
End Using
End Sub)
container.Verify()
Return container
End Function
For some reason, in the VB version, the app.Use() doesn't use the extension function that's available and simply uses IAppBuilder.Use() instead, as follows:
Function Use(middleware As Object, ParamArray args() As Object) As IAppBuilder
Why does the VB code not use the same extension function that C# does and how can I make it use that?
Edit
For clarity, the extension methods are not my own. They are from the Owin 3rd party library. So there is no option of renaming the extension methods.

In the C# code because next is Func and await returns a task, there is no return statement, but actualy a Task object is returned.
IMO the VB.NET code does not return a Task object, because the lambda is specified as Sub (= Action in C#).
Changing the Sub to Func in the VB.NET code should call the wanted method.

In VB (fiddle), you can pass a lambda expression when an object is required:
Public Shared Sub Main()
MyMethod(Function() True) ' compiles
End Sub
Public Shared Sub MyMethod(o As Object)
End Sub
In C# (fiddle), that doesn't work:
public static void Main()
{
// Compilation error: Cannot convert lambda expression to type 'object' because it is not a delegate type.
// You'd need to use: MyMethod(new Func<bool>(() => true));
MyMethod(() => true);
}
public static void MyMethod(object o) { }
This is probably due to the fact that lambda expressions can be implicitly converted to delegates in VB but not in C#:
' Compiles
Dim d As System.Delegate = Function() True
// Compilation error: Cannot convert lambda expression to type 'Delegate' because it is not a delegate type
System.Delegate d = () => true;
Thus, in your code example, VB finds a matching suitable instance method and uses it. In the C# code, no matching instance method is found (since your lambda expression does not match object), and the extension method is used instead.
Note that both languages prefer instance methods over extension methods if a matching method is found. This can lead to subtle bugs if a matching instance method is added later.
How to fix that? I suggest to use different names for the extension method and the instance method - other developers reading your code in the future will thank you for it. If that's not an option, you can always call the extension method explicitly:
Owin.AppBuilderUserExtensions.Use(app, Async Sub(context, [next]) ...)

Related

How do I call the following constructor Func<T> as in SimplSocket(Func<System.IO.Sockets.Socket> socketFunc)

I'm not familiar with this API, but I'm trying to create a new constructor that requires a parameter of Func as shown in the constructor below
public SimplSocket(System.Func<System.Net.Sockets.Socket> socketFunc,
int messageBufferSize,
int maximumConnections,
bool useNagleAlgorithm)
What do I do with socketFunc?
System.Func<System.Net.Sockets.Socket> is a so called delegate. They are used to hold functions. In this special case the delegate only accepts functions that return a System.Net.Sockets.Socket type and that have no arguments. For example:
You have a function defined somewhere:
public System.Net.Sockets.Socket someFunction()
{
//whatever it does
}
Then you can do this:
var sock = new SimplSocket(someFunction, 1024,1,false);
If you don't want to define an extra function you could use lambda expression to express the function directly:
var sock = new SimplSocket(() => new System.Net.Sockets.Socket(...), 1024,1,false);
The constructor itself can use delegate socketFunc to call the given function and it knows that the function will return a System.Net.Sockets.Socket but doesn't know which function is used. This would simply look like this:
var aSock = socketFunc();

Passing a method as a parameter with zero or more parameters for the passed in method?

I'm trying to code what I've called a 'trigger'. They take an object, a function and some kind of activation criteria. Once activated, it runs the method on that object.
Here's a basic stripped down example. It works as expected for now. An example usage would be:
SomeObject myObj = new SomeObject();
MyTrigger trigger = new MyTrigger(myObj, "Delete");
trigger.Activate(); // calls myObj.Delete();
Now where I've called Invoke with null is where parameters can normally go (I think). The problem I'm having is getting the 'zero or more paramters' as a single parameter in the function declaration. I need a thrid parameter when creating MyTrigger that would be the parameters to pass during the Invoke.
Or is there an even better way to do it? I.e. Can I somehow pass the object, the function call and the parameters as a single parameter? Maybe two parameters?
You have to use delegates.
// rewrite your trigger constructor like this
class MyTrigger<TTarget>
{
public MyTrigger(TTarget target, Action<TTarget> action);
public void Activate()
{
this._action(this._target);
}
}
// now call it with or without parameters
SomeObject myObj = new SomeObject();
var trigger = new MyTrigger<SomeObject>(myObj, o => o.Delete(1234));
trigger.Activate();
You can also create a static helper class to make the creation code slightly simpler to write:
static class MyTrigger
{
public MyTrigger<TTarget> Create<TTarget>(TTarget target, Action<TTarget> action)
{
return new MyTrigger<TTarget>(target, action);
}
}
// now write the initialization code like this (you don't have to specify the type parameter anymore):
var trigger = MyTrigger.Create(myObj, o => o.Delete());
You could use the params keyword:
public Trigger(object targetObject, string methodName, params object[] parameters)
{
//"parameters" here will be an array of length 0 if no parameters were passed
}
MyTrigger trigger = new MyTrigger(myObj, "Delete"); //no parameters
MyTrigger trigger = new MyTrigger(myObj, "Delete", param1); //one parameter
MyTrigger trigger = new MyTrigger(myObj, "Delete", param1, param2); //two parameters
But I prefer Knagis' answer because it will also provide you compile-time safety (and likely the Trigger class will be far simplified and ditch any reflection that you probably have in there.)

generic delegate creation using Expression in C#

Given below are two methods which create a delegate to set a field in a class. One method uses generics and the other does not.
Both the methods return a delegate and they work fine. But if I try to use the delegate that has been created inside the CreateDelegate method, then the non-generic delegate 'del' works fine. I can place a breakpoint on the return statement and invoke the delegate by writting del(222). But If I try to invoke the generic delegate 'genericDel' by writting genericDel(434), it throws an exception:
Delegate 'System.Action' has some invalid arguments
Can anyone explain this quirk.
class test
{
public double fld = 0;
}
public static void Main(string[] args)
{
test tst = new test() { fld = 11 };
Type myType = typeof(test);
// Get the type and fields of FieldInfoClass.
FieldInfo[] myFieldInfo = myType.GetFields(BindingFlags.Instance | BindingFlags.Public);
var a = CreateDelegate<double>(myFieldInfo[0], tst);
var b = CreateDelegate(myFieldInfo[0], tst);
Console.WriteLine(tst.fld);
b(5.0);
Console.WriteLine(tst.fld);
a(6.0);
Console.WriteLine(tst.fld);
}
public static Action<T> CreateDelegate<T>(FieldInfo fieldInfo, object instance)
{
ParameterExpression numParam = Expression.Parameter(typeof(T), "num");
Expression a = Expression.Field(Expression.Constant(instance), fieldInfo);
BinaryExpression assExp = Expression.Assign(a, numParam);
Expression<Action<T>> expTree =
Expression.Lambda<Action<T>>(assExp,
new ParameterExpression[] { numParam });
Action<T> genericDel = expTree.Compile();
//try to invoke the delegate from immediate window by placing a breakpoint on the return below: genericDel(323)
return genericDel;
}
public static Action<double> CreateDelegate(FieldInfo fieldInfo, object instance)
{
ParameterExpression numParam = Expression.Parameter(typeof(double), "num");
Expression a = Expression.Field(Expression.Constant(instance), fieldInfo);
BinaryExpression assExp = Expression.Assign(a, numParam);
Expression<Action<double>> expTree =
Expression.Lambda<Action<double>>(assExp,
new ParameterExpression[] { numParam });
Action<double> del = expTree.Compile();
//try to invoke the delegate from immediate window by placing a breakpoint on the return below: del(977)
return del;
}
I think I understood the issue; you are having problems invoking a generic delegate from the immediate window when the compile-time type of the delegate is an open generic type.
Here's a simpler repro:
static void Main() { Test<double>(); }
static void Test<T>()
{
Action<T> genericDel = delegate { };
// Place break-point here.
}
Now, if I try executing this delegate from within the Test method (by placing a break-point and using the immediate window) like this:
genericDel(42D);
I get the following error:
Delegate 'System.Action<T>' has some invalid arguments
Note that this not an exception like you have stated, but rather the 'immediate window version' of compile-time error CS1594.
Note that such a call would have failed equally at compile-time because there is no implicit or explicit conversion from double to T.
This is debatably a shortcoming of the immediate window (it doesn't appear to be willing to use additional 'run-time knowledge' to help you out in this case), but one could argue that it is reasonable behaviour since an equivalent call made at compile-time (in source code) would also have been illegal. This does appear to be a corner case though; the immediate window is perfectly capable of assigning generic variables and executing other code that would have been illegal at compile-time. Perhaps Roslyn will make things much more consistent.
If you wish, you can work around this like so:
genericDel.DynamicInvoke(42D);
(or)
((Action<double>)(object)genericDel)(42D);
The problem is that you are trying to invoke the delegate within the scope of the method that is creating it, before 'T' is known. It is trying to convert a value type (an integer) to the generic type 'T', which is not allowed by the compiler. If you think about it, it makes sense. You should only be able to pass in T as long as you are within the scope of the method that is creating the delegate, otherwise it wouldn't really be generic at all.
You need to wait for the method to return, then use the delegate. You should have no problem invoking the delegate after its completed:
var a = CreateDelegate<double>(myFieldInfo[0], tst);
var b = CreateDelegate(myFieldInfo[0], tst);
a(434);

How do I access a class module in Excel VBA from C#?

I have an Excel add-in with a class module. I want to instantiate the class module in C# and call a method on it. How do I do that?
If you really need access to an instance of the class, you could do the following:
Generate a type library for a COM interface that you want to expose from your VBA class (e.g. IMyComInterface)
Add a reference to this type library in your VBA project
Implement the interface in your VBA class module - e.g. MyVbaClass (use the Implements keyword):
Option Explicit
Implements IMyComInterface
Private Sub IMyComInterface_SomeMethod(...)
...
End Sub
...
Reference the same type library in your C# project
Create a ComVisible C# class with a method that accepts a reference to the VBA interface instance. Something like:
public class MyVbaLoader
{
public IMyComInterface MyComInterface
{
get { return myComInterface; }
set { myComInterface = value; }
}
}
Write a "factory" method in a VBA standard module, that takes an object as a ByRef parameter. This object should assume the object passed as an argument has a property "MyComInterface" and should set this property to a new instance of the VBA class MyClass.
Public Sub MyFactoryMethod(MyVbaLoader As Object)
Dim objClass As MyVbaClass
Set objClass = New MyVbaClass
... any initialization of objClass here ...
' Pass a reference to the VBA class to the C# object MyVbaLoader
MyVbaLoader.MyComInterface = objClass
End Sub
Call the factory method from your C# code. Assuming you have opened the workbook and have a refence "workbook" in your VBA code, the code will look something like:
MyVbaLoader loader = new MyVbaLoader();
workbook.Application.Run("MyModule.MyFactoryMethod", loader, Type.Missing, ... , Type.Missing);
// we now have a reference to the VBA class module in loader.MyComInterface
// ...
As you can see, it's rather complex. Without more detail of the problem you're trying to solve it's difficult to say whether this complexity is justified, or whether there's a simpler solution.
If the above isn't clear, let me know and I'll try to clarify.
Basically you can't return a value from a VBA macro called from your C# code using Application.Run, so you have to resort to passing an object by value that has a method or property that can be called from VBA to set the instance.
VBA class modules have only two instancing modes: private, and public-not-creatable. So, you can't even instantiate them in another VB(A) project, let alone from C#.
However, there's nothing to stop you having a standard module that acts as a class factory. So, if your class module is Foo then you can have a method in a standard module called NewFoo that instantiates a new Foo for you and returns it to the caller. The Foo object would obviously have to be public-not-creatable.
[Your NewFoo method can take parameters, so you can simulate parameterized constructors, which aren't available in VBA.]
EDIT: detail on how to call VBA function (in a standard module) from C# and get the return value using Application.Run.
private static object RunMacro(Excel.Application excelApp, string macroName, object[] parameters)
{
Type applicationType = excelApp.GetType();
ArrayList arguments = new ArrayList();
arguments.Add(macroName);
if (parameters != null)
arguments.AddRange(parameters);
try
{
return applicationType.InvokeMember("Run", BindingFlags.Default | BindingFlags.InvokeMethod, null, excelApp, arguments.ToArray());
}
catch (TargetInvocationException ex)
{
COMException comException = ex.InnerException as COMException;
if (comException != null)
{
// These errors are raised by Excel if the macro does not exist
if ( (comException.ErrorCode == -2146827284)
|| (comException.ErrorCode == 1004))
throw new ApplicationException(string.Format("The macro '{0}' does not exist.", macroName), ex);
}
throw ex;
}
}
Note that you could omit all that try...catch stuff - all it's doing is handling the specific error where the macro does not exist and raising a more meaningful exception in that case.
The object returned from the function can be cast to whatever type you need. For example:
object o = RunMacro(excelApp, "MyModule.MyFunc", new object[] { "param1", 2 });
if (o is string)
{
string s = (string) o;
Console.WriteLine(s);
}
Assuming that the function actually returns an instance of your VBA-defined class object, then you can call the methods of that object in the same way, again using InvokeMember:
object o = RunMacro(excelApp, "MyModule.MyFunc", new object[] { "param1", 2 });
// assume o is an instance of your class, and that it has a method called Test that takes no arguments
o.GetType().InvokeMember("Run", BindingFlags.Default | BindingFlags.InvokeMethod, null, o, new string[] {"Test"});
If you're doing a lot of these calls, then obviously you can hide the ugly detail by creating wrapper methods to make the call for you.
Please note that I've typed most of this from memory, so I fully expect there to be syntax, logical and possibly even factual errors :-)

C# - Can someone tell me why and where I should use delegates? [duplicate]

This question already has answers here:
Where do I use delegates? [closed]
(8 answers)
Closed 9 years ago.
I think I understand the concept of a delegate in C# as a pointer to a method, but I cant find any good examples of where it would be a good idea to use them. What are some examples that are either significantly more elegant/better with delegates or cant be solved using other methods?
The .NET 1.0 delegates:
this.myButton.Click += new EventHandler(this.MyMethod);
The .NET 2.0 delegates:
this.myOtherButton.Click += delegate {
var res = PerformSomeAction();
if(res > 5)
PerformSomeOtherAction();
};
They seem pretty useful. How about:
new Thread(new ThreadStart(delegate {
// do some worker-thread processing
})).Start();
What exactly do you mean by delegates? Here are two ways in which they can be used:
void Foo(Func<int, string> f) {
//do stuff
string s = f(42);
// do more stuff
}
and
void Bar() {
Func<int, string> f = delegate(i) { return i.ToString(); }
//do stuff
string s = f(42);
// do more stuff
}
The point in the second one is that you can declare new functions on the fly, as delegates. This can be largely replaced by lambda expressions,and is useful any time you have a small piece of logic you want to 1) pass to another function, or 2) just execute repeatedly. LINQ is a good example. Every LINQ function takes a lambda expression as its argument, specifying the behavior. For example, if you have a List<int> l then l.Select(x=>(x.ToString()) will call ToString() on every element in the list. And the lambda expression I wrote is implemented as a delegate.
The first case shows how Select might be implemented. You take a delegate as your argument, and then you call it when needed. This allows the caller to customize the behavior of the function. Taking Select() as an example again, the function itself guarantees that the delegate you pass to it will be called on every element in the list, and the output of each will be returned. What that delegate actually does is up to you. That makes it an amazingly flexible and general function.
Of course, they're also used for subscribing to events. In a nutshell, delegates allow you to reference functions, using them as argument in function calls, assigning them to variables and whatever else you like to do.
I primarily use the for easy asynch programming. Kicking off a method using a delegates Begin... method is really easy if you want to fire and forget.
A delegate can also be used like an interface when interfaces are not available. E.g. calling methods from COM classes, external .Net classes etc.
Events are the most obvious example. Compare how the observer pattern is implemented in Java (interfaces) and C# (delegates).
Also, a whole lot of the new C# 3 features (for example lambda expressions) are based on delegates and simplify their usage even further.
For example in multithread apps. If you want several threads to use some control, You shoul use delegates. Sorry, the code is in VisualBasic.
First you declare a delegate
Private Delegate Sub ButtonInvoke(ByVal enabled As Boolean)
Write a function to enable/disable button from several threads
Private Sub enable_button(ByVal enabled As Boolean)
If Me.ButtonConnect.InvokeRequired Then
Dim del As New ButtonInvoke(AddressOf enable_button)
Me.ButtonConnect.Invoke(del, New Object() {enabled})
Else
ButtonConnect.Enabled = enabled
End If
End Sub
I use them all the time with LINQ, especially with lambda expressions, to provide a function to evaluate a condition or return a selection. Also use them to provide a function that will compare two items for sorting. This latter is important for generic collections where the default sorting may or may not be appropriate.
var query = collection.Where( c => c.Kind == ChosenKind )
.Select( c => new { Name = c.Name, Value = c.Value } )
.OrderBy( (a,b) => a.Name.CompareTo( b.Name ) );
One of the benefits of Delegates is in asynchronous execution.
when you call a method asynchronously you do not know when it will finish executing, so you need to pass a delegate to that method that point to another method that will be called when the first method has completed execution. In the second method you can write some code that inform you the execution has completed.
Technically delegate is a reference type used to encapsulate a method with a specific signature and return type
Some other comments touched on the async world... but I'll comment anyway since my favorite 'flavor' of doing such has been mentioned:
ThreadPool.QueueUserWorkItem(delegate
{
// This code will run on it's own thread!
});
Also, a huge reason for delegates is for "CallBacks". Let's say I make a bit of functionality (asynchronously), and you want me to call some method (let's say "AlertWhenDone")... you could pass in a "delegate" to your method as follows:
TimmysSpecialClass.DoSomethingCool(this.AlertWhenDone);
Outside of their role in events, which your probably familiar with if you've used winforms or asp.net, delegates are useful for making classes more flexible (e.g. the way they're used in LINQ).
Flexibility for "Finding" things is pretty common. You have a collection of things, and you want to provide a way to find things. Rather than guessing each way that someone might want to find things, you can now allow the caller to provide the algorithm so that they can search your collection however they see fit.
Here's a trivial code sample:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace Delegates
{
class Program
{
static void Main(string[] args)
{
Collection coll = new Collection(5);
coll[0] = "This";
coll[1] = "is";
coll[2] = "a";
coll[3] = "test";
var result = coll.Find(x => x == "is");
Console.WriteLine(result);
result = coll.Find(x => x.StartsWith("te"));
Console.WriteLine(result);
}
}
public class Collection
{
string[] _Items;
public delegate bool FindDelegate(string FindParam);
public Collection(int Size)
{
_Items = new string[Size];
}
public string this[int i]
{
get { return _Items[i]; }
set { _Items[i] = value; }
}
public string Find(FindDelegate findDelegate)
{
foreach (string s in _Items)
{
if (findDelegate(s))
return s;
}
return null;
}
}
}
Output
is
test
there isn't really anything delgates will solve that can't be solved with other methods, but they provide a more elegant solution.
With delegates, any function can be used as long as it has the required parameters.
The alternative is often to use a kind of custom built event system in the program, creating extra work and more areas for bugs to creep in
Is there an advantage to use a delegate when dealing with external calls to a database?
For example can code A :
static void Main(string[] args) {
DatabaseCode("test");
}
public void DatabaseCode(string arg) {
.... code here ...
}
Be improved in code B :
static void Main(string[] args) {
DatabaseCodeDelegate slave = DatabaseCode;
slave ("test");
}
public void DatabaseCode(string arg) {
.... code here ...
}
public delegate void DatabaseCodeDelegate(string arg);
It seems that this is subjective, but an area where there are strong conflicting view points?

Categories

Resources