Refer to C# method from JavaScript without calling it - c#

I have a WebBrowser control set up with ObjectForScripting such that I can call C# methods from JavaScript hosted in the browser control.
Everything seems to be going fine except that in my unit tests I have some checks on the window.external methods I am using and it turns out that...
window.external.MyMethod
...seems to work just the same as...
window.external.MyMethod()
What if I need a reference to the method? Or in the case of my unit test:
typeof(window.external.MyMethod) === 'function'
But this calls the method (and fails because it returns the type of whatever was returned by the method)
How do I get a reference to the method without calling it?

Looking at what documentation I could find, it looks like referring to any member of window.external initiates a call to the host:
...a reference to "window.external.speech" will call the host to resolve the name "speech."
I'm not specifically familiar with this API, but it seems like you might be able instead to do something like:
window.external.checkType('MyMethod') === 'function'
Where checkType is a function you declare within your C# code that can tell you the type of the property provided.

Related

Pythonnet passing arguments to c# dll

I'm using Pythonnet 2.4.0 to access a C# dll. I have a Windows 10 machine with Python 3.7.6.
I'm trying to use a method that only takes a path string as argument, but I don't manage to make it work.
import clr
sys.path.append(os.getcwd)
clr.AddReference('C#Wrapper')
path = "C:\\Users\\Username\\Folder"
c#class.method(string path)
If I use the overloads attribute from pythonnet, it tells me that the argument should be of type System.String, however doing something like below didn't help either:
path = System.String("C:\\Users\\Username\\Folder")
I keep getting a TypeError: No Method matches given arguments.
Do I need to encode the string or make a char array in order for c# to be able to understand it?
Edit:
I've just found a test function in the dll that only takes an Int32 argument and I have the same problem! I tried things like:
import ctypes
c#class.testmethod(ctypes.c_int32(1))
from System import Int32
c#class.testmethod(Int32(1))
but nothing worked. How can I pass arguments to the c# dll?
[Solved]:
I figured it out myself. In the second case I simply forgot to instantiate a class object. I should have done:
classobj = c#class()
classobj.testmethod(1)
This made me realize that in the first case I had basically the same issue. I followed a Visual Basic manual to write my Python program where it said something like this:
classobj = c#class
However in Python you need to write:
classobj = c#class()
So the missing parenthesis was causing the TypeError: No Method matches given arguments, which was very misleading. The type conversion and passing of arguments is perfectly handled thanks to the amazing developers of phythonnet! I won't delete this question in case other people experience the same issue.
The answer above is correct: Pythonnet passing arguments to c# dll.
I'd just like clarify what it means.
The error occurred because a method from a class was accessed without instantiating the object.
The solution is one of the two:
create an instance of the class
mark the .net method as static
The problem was that the error message is misleading, it says "No method matches given arguments". Which made me try to find the right argument.
By me this occurred when I forgot to add the static modifier to the .net method I called.

C# - require a returned type to be assigned to an L-Value?

this may not be sensible,
but i'm looking at a situation where i would like it to be a compile error if the return value of a method goes unused.
specifically, Unity3D implements coroutines which look like this:
IEnumerator myCoroutine() {... yield break;}
if you call myCoroutine() and do nothing with the returned value (eg, you're calling it like a normal method, not from inside another yield clause or via the StartCoroutine() method), the result is that all the code inside myCoroutine() is not executed. however, there is no compile- or runtime- warning. i would like to get a compile-time error in this scenario.
one approach i thought of is to subclass IEnumerator into say MyIEnumerator, which adds the property that it must be passed on in some way - either assigned to an L-Value or passed to a method, etc.
but i haven't been able to discover if such a requirement exists.
There is no such feature in C# for this. You'd need to create some form of 3rd party code analysis tool to try to look for cases such as these.

Pass a callback function from Visual Basic to C#

I have a .dll written in C# and I use it in Visual Basic for making a Com object. I call C# functions from my Visual Basic code. I'm quite new to this technology and I encountered with such a problem. In C# code I have a method, that receives a callback function as a parameter, gets data from server then calls that callback function. Now I need to to call that function from my Visual Basic code and pass to it a callback.
I think it should look something like this
// C# dll
public bool GetDataFromServer(int someData1, Action<MyCustomType> callback, int someData2)
{
// request to server, get data, create an object of MyCustomType
// call callback and pass MyCustomType object to it as a parameter
}
// Visual Basic part
Public Sub DisplayData(ByRef resp As My_Dll.MyCustomType)
' do something with resp
End Sub
// call Dll method
My_Dll.GetDataFromServer(1, DisplayData, 2) ' I get a compile error
But I can't get it work, it event does not compile. I get a compilation error saying "Argument not optional". I've also tried to pass callback function with AddressOf, but I get an error again saying - "Invalid use of AddressOf operator".
Now my question is - what am I doing wrong? What is the correct way of passing a callback function from Visual Basic to C# and then get it invoked.
Thank you for your time!
Anything containing generics is not visible to COM, so your GetDataFromServer with Action<MyCustomType> is not COM visible. You must define a method on a non-generic class without generic type arguments of itself and without generic parameter or return types.
The usual way of passing a callback in COM is to pass an interface pointer with a method to be called. Avoid the AddressOf approach, however feasible, it's really bad practice once you want the callback to work out-of-process.
A common trick with IDispatch objects is to define a class with a default method with DispId 0 (DISPID_VALUE), which may be invoked by the COM server through IDispatch::Invoke. In some languages, such as JScript, objects may be callable through this technique.
To see how you can do this in VB6/VBA, search for VB_UserMemId. Essentially, you must edit the class file in its raw format (in VBA, you must export it) and add an attribute, such as:
Sub Call()
Attribute Call.VB_UserMemId = 0
End Sub
In VBA, you'd delete the class and import from the edited file. The effect is that the Call method now has DispId 0. You may call it whatever you want, but remember to edit both the Sub name and the Attribute.
In C#, I believe the only ways to achieve such call is with a dynamic variable with:
obj[0]
or through Type.InvokeMember or similar IDispatch::Invoke approaches:
obj.GetType().InvokeMember("", BindingFlags.InvokeMethod, null, obj, null);
The latter is more reliable and you pass the arguments you want, while the former uses a misleading syntax and forces you to pass an argument.
In general, if you control the whole situation and you don't need callable objects, just go for a plain method.
Regarding the AddressOf error, this operator works on module procedures and functions, so the error you see is probably because DisplayOptionQuotes is a method.

ObjectDataSource SelectMethod and SelectCountMethod

When using an ObjectDataSource control, either instance methods or static methods can be used for the SelectMethodand SelectCountMethod. According to the MSDN documentation, if an instance method is used, a new instance will be created and disposed upon completion.
If it is an instance method, the business object is created and
destroyed each time the method that is specified by the SelectMethod
property is called.
However, according to this in-depth walkthrough, if paging is enabled and both the SelectMethod and SelectCountMethod are instance methods, the same instance is used when calling these methods.
If we have enabled paging and our SelectMethod and SelectCountMethod
are instance methods, the same instance is used when calling both
methods, so we can save the total number of registers in a field in
the SelectMethod and then we can return it in the SelectCountMethod.
In another reference, the information provided (apparently by a member of the MS ASP.NET team) contradicts the information above.
However you should realize that different instances are used to call
the Select and SelectCount method ...
My question: Which of these behaviors is the actual one implemented in asp.net? Is the same instance used when calling those methods, or are they called by different instances?
I have attempted (in .net 3.5 VS 2008) to implement paging using the first reference (which says they are called by the same instance), and it does work for me. When I set the record count into a non-static variable/field in the SelectMethod, the same value is indeed returned when SelectCountMethod is called. I suppose that should mean that the same instance is used, contrary to the information in the second reference, and that it would be safe for me to set the record count in the SelectMethod and return it in the SelectCountMethod using a non-static variable. However, I'd prefer if someone could actually confirm this, as the first reference is quite old (written in 06), and I have no way of testing if this behavior has been changed in newer versions (.net 4.0 and up).
Please let me know if my question is unclear, or if there is an official reference that can answer my question.

How does "static reflection" work in java? (ex. in mockito or easymock)

I'm a .NET guy - and I mainly code in C#.
Since C# 3.0, we can leverage lambda expressions and expression trees to use static reflection. For example, it is possible to implement GetMethodName in the following snippet to return the name of the method passed in parameter:
string methodName = GetMethodName( o => o.DoSomething());
Console.WriteLine(methodName); // displays "DoSomething"
Now, when I look at Mockito samples (or EasyMock ones) in the java world, I see:
LinkedList mockedList = mock(LinkedList.class);
when(mockedList.get(0)).thenReturn("first");
How does it work?
How does the when method work ? How does it interpret mockedList.get(0) as a call to the get method with 0 passed as parameter and not as a value?
Mocking libraries don't typically work with expression trees. They build a type which implements the appropriate interface and responds to method calls either by recording them or validating them and returning the preprogrammed responses. This is usually done with either a proxy (e.g. RealProxy in .NET, Proxy in Java) or with dynamic code generation.
In the case of EasyMock, it uses Proxy (for interfaces, anyway), as you can see in the source code: look at org.easymock.internal.JavaProxyFactory.
Java mock libraries usually work like this:
When you create a mock, an actual proxy is created (be it from an interface or a sub-class), the instance is in "recording mode". This means that any subsequent call is recorded (method name, parameters, return expected). Notice that the proxy in recording mode does actually nothing but record the calls. There is no reflection per-se involved. No metadata discovery, etc. Of course these libraries do some tricks (such as storing invocations in a thread-local variable to handle methods that return void) but the idea remains the same.
Then, when the "replay mode" is started, the mock instance simply checks the expectations from the list of invocations (method+parameters & return values).
I’ve never worked with mockito or easymock but I don’t think the call does what you think it does. It does not interpret mockedList.get(0) in any special way. The method get is executed on the mockedList object normally, and the result of that is handed in to when.
mockedList.get(0) is the syntax for a method call, and does exactly that. What that method does is not exactly clear. mockedList's runtime type will be a subclass of LinkedList returned by the mock method, which can be implemented how ever the mocking framework sees fit.

Categories

Resources