Search code examples
java.netgenericsjava-native-interfacejavonet

javonet : how to create a NNull on generic class


I am evaluating javonet to call a C# dll from java. As i see it's the more compliante to my context (generic fail with jni4net, and JnBridge don't export all my type)

I want to call a method with null instance on a complex generic.

System.Func<MyType<MySubType>, MyOtherType, MyAnotherType>

I try to call without generic but javonet don't find the method.

new NNull("System.Func")

I try to call with the return but javonet again don't find the method.

new NNull("System.Func`3[MyType`1[MySubType],MyOtherType,MyAnotherType]")

I don't find generic way to call NNull ? Is there any ?

Thanks by advance for any help ;o)


Solution

  • If there is only one method with matching number of arguments (no overloads) then you can easily pass "null".

    However because the Javonet invoke(String, Object...) method expects method name and any number of params if you want to pass single argument null you must call obj.invoke("MethodName", new Object[] {null}); so Java knows that you pass single argument null not the null array what would mean no arguments at all.

    In your case on .NET side:

    public class ObjA
    {
        public void MethodA(Func<MyType<MySubType>, MyOtherType, MyAnotherType>  arg)
        {
            Console.WriteLine("Called MethodA");
        }
    }
    
    public class MyType<T>
    {
    
    }
    public class MySubType
    {
    
    }
    
    public class MyOtherType
    {
    
    }
    
    public class MyAnotherType
    {
    
    }
    

    And to call it from Java using Javonet you make simply:

        NObject objA = Javonet.New("ObjA");
        objA.invoke("MethodA",new Object[] {null});
    

    The NNull type is needed only if there is another method with the matching number of arguments when .NET cannot deduct from the null passed which method should be called. In example:

    public void MethodA(Func<String> arg1);
    public void MethodA(Func<int> arg1);
    

    With multiple overloads

    On the other hand if you have multiple overloads of the method with same number of arguments and want to pass null instead of your complex argument the same as in pure .NET you must cast null to the expected type:

    public class ObjA
    {
        public void MethodA(Func<MyType<MySubType>, MyOtherType, MyAnotherType> arg, int arg2)
        {
            Console.WriteLine("Called MethodA with args: Func<MyType<MySubType>, MyOtherType, MyAnotherType> arg, int arg2");
        }
        public void MethodA(Func<MyOtherType> arg, int arg2)
        {
            Console.WriteLine("Called MethodA with args: Func<MyOtherType> arg, int arg2");
        }
    }
    

    In .NET you would call:

    MethodA((Func<MyType<MySubType>, MyOtherType, MyAnotherType>)null, 0);
    

    You can still get the same done in Java using the Javonet 1.4hf26-SNAPSHOT release available here: http://download.javonet.com/1.4/javonet-1.4hf26-SNAPSHOT.jar

    It is not official release but it is stable and can be used. That patch includes possibility to pass NType as argument to NNull object. In that case you would be able to construct your complex generic type with Javonet generic types creation syntax as in example below:

        NType myAnotherType = Javonet.getType("MyAnotherType");
        NType myOtherType = Javonet.getType("MyOtherType");
        NType mySubType = Javonet.getType("MySubType");
        NType myType = Javonet.getType("MyType`1",mySubType);
        NType func = Javonet.getType("Func`3",myType,myOtherType,myAnotherType);
    
        NObject objA = Javonet.New("ObjA");
        objA.invoke("MethodA",new NNull(func),0);