Wednesday, December 29, 2010

A Pretty Functional Dynamic Proxy for jni4net

Wish you could use the dynamic keyword to access java objects created using jni4net?  I use this class to do that.  Feel free to reproduce it, modify it, or incorporate it into your own products so long as you don't claim that it is "yours" and start suing other people who use it.

It's cut-and-pasted out of my code so there's no guarantee that you won't need to tweak it a little. One might say it's pretty much guaranteed that you will. :)

using net.sf.jni4net;
using System.Dynamic;

public class JavaObjectProxyFactory
{
  public class JavaObjectProxy : DynamicObject
  {
    private readonly java.lang.Object o;
    private readonly java.lang.Class c;

    private JavaObjectProxy(
      java.lang.Object o,
      java.lang.Class c)
    {
      this.o = o;
      this.c = c;
    }

    public static dynamic GetInstance(
      java.lang.Object o,
      java.lang.Class c)
    {
      return new JavaObjectProxy(o, c);
    }

    public override bool TryGetMember(
      GetMemberBinder binder,
      out object result)
    {
      var field = c.getField(binder.Name);

      if (field == null)
      {
        result = null;
        return false;
      }

      result = ConvertToDotNetObject(field.get(o));

      return true;
    }

    public override bool TrySetMember(
      SetMemberBinder binder,
      object value)
    {
      var field = c.getField(binder.Name);

      if (field == null)
      {
        return false;
      }

      field.set(o, ConvertToJavaObject(value));
      return true;
    }

    public override bool TryInvokeMember(
      InvokeMemberBinder binder,
      object[] args,
      out object result)
    {
      var signature = new java.lang.Class[
        binder.CallInfo.ArgumentCount];
      var arguments = new java.lang.Object[
        binder.CallInfo.ArgumentCount];

      for (var i = 0; i < args.Length; ++i)
      {
        java.lang.Object arg = 
          ConvertToJavaObject(args[i]);
        if (arg != null)
        {
          signature[i] = arg.getClass();
          arguments[i] = arg;
        }
      }

      var method = c.getMethod(binder.Name, signature);
      if (method == null)
      {
        result = null;
        return false;
      }

      result = ConvertToDotNetObject(
        method.invoke(o, arguments));

      return true;
    }

    private object ConvertToDotNetObject(
      java.lang.Object o)
    {
      if (o == null)
      {
        return null;
      }

      if (o is java.lang.String)
      {
        var s = (java.lang.String)o;
        return new string(s.toCharArray());
      }

      return GetDynamicProxy(o);
    }

    private java.lang.Object ConvertToJavaObject(
      object p)
    {
      if (p == null)
      {
        return null;
      }

      if (p is string)
      {
        return new java.lang.String((string)p);
      }

      return (java.lang.Object)p;
    }
  }

  public static dynamic GetDynamicProxy(
    java.lang.Object o)
  {
    if (o == null)
    {
      return null;
    }

    return JavaObjectProxy.GetInstance(o, o.getClass());
  }
}

Enjoy.

Friday, December 17, 2010

"Happy Holidays" is what terrorists say. Merry Christmas!

Even though I'm not a Christian, merry Christmas everyone.

As a gift to the public at large, I've lowered the price of the Goad Testing PDF to free.  So get your copy now.

-- Max