Category: Proxy usage
How do I cast a proxy object to another proxy type?
Many times, the Codemesh runtime will be smart enough to return a property typed .NET object from a method call or property access and all you have to do is cast the object ot the desired type. Sometimes, the Codemesh runtime does not have the required knowledge to perform this operation and then you have to use the generated From() method.
Let's take a look at a typical Java method, for example the Hashtable class' put() method. It is declared as follows:
Java Object put( Object key, Object value );
The corresponding .NET method looks like this (some framework arguments omitted for clarity):
.NET object Put( object key, object value );
All that we could know about this method when we created it is that the put() method can return anything. At runtime, the returned Java object is only very rarely going to be of type Object; it's much more likely to be a String or an application-specific data type. In order to return the best .NET type from the method call, the Codemesh runtime performs a Java type analysis and, based on its outcome, returns a proxy instance of a type that most closely resembles the Java type of the object.
This works great if there is an exact proxy type for the returned Java type. A Java String turns into a .NET string, a Java Object turns into a proxy Java.Lang.Object, etc. But what happens when we don't have an exact proxy type for the Java object? In this case, the Codemesh runtime goes up the inheritance hierarchy until it finds a matching proxy type.
This approach often yields a good result, and it always yields a correct result, but sometimes that correct result does not allow you to perform a subsequent cast. How come? Let's assume that a returned object implements two different, unrelated interfaces and that there is no proxy type available that inherits from both proxy interfaces. In such a case, the Codemesh runtime has to essentially pick one of the interfaces as the return type. The runtime will wrap the Java object in the implementation type of one of the interfaces and return the proxy instance. So far so good. Now you come along and try to cast the returned object to the other interface. Your application crashes with an InvalidCastException from the .NET side. The cast is valid on the Java side, but not on the .NET side.
If you want to be totally certain that the "cast" works, you have to use the static From() method that is declared by the interface Impl types, for example:
C++ Serializable oldvalue = SerializableImpl::From( ht.put( "key", "newvalue" ) );
Just to reiterate:
You only need to use From() if there is no exact proxy type or no proxy type that implements all proxy interfaces.