Showing posts with label reflection. Show all posts
Showing posts with label reflection. Show all posts

Saturday, August 11, 2018

How to get reflected runtime Method from AnyRef object?

Leave a Comment

I am trying to get the reflected runtime method in an instance but it is not shown in the decls result:

val foo: AnyRef = new Object {   def bar = 1 } typeOf[foo.type].decls //Does not contain bar method 

I tried to use Java reflection class and it works:

foo.getClass.getDeclaredMethods //It contains bar method 

But I prefer to work with MethodSymbols and Scala Type than Java Class and Method reflection. How can I get the reflected MethodSymbol?


I want an method to look up an object passed as AnyRef for a method bar and call it. Something like below:

def getBarMethodFromObj(obj: AnyRef): MethodSymbol = {   //typeOf(obj).decl(TermName("bar")) this doesn't work } 

I cannot use trait because bar can have different argument and return types and numbers. As Scala does not support varadic generic arguments, I plan to use reflection to find the method and call, but this cannot be done in Scala as well. I am currently use Java solution:

val bar = foo.getClass.getDeclaredMethods.find(_.getName == "bar") bar.invoke(foo, params: _*) 

However Java reflection does not retain generic types as it creates problem for List and Map, etc. So I want to know if I can implement this in Scala, or is there any coming solution

1 Answers

Answers 1

I don't know what you're trying to do, but removing the AnyRef annotation makes your code work:

val foo = new { def bar = 1 } typeOf[foo.type].decls // Contains bar method 

If you need a type annotation (for example, in a method signature), you can use the same structural type that the compiler infers:

val foo: { def bar: Int } = new { def bar = 1 } 

If you want to get the full list of methods from another method without knowing the exact type except via generics, you may be interested in TypeTag:

import scala.reflect.runtime.universe.{ TypeTag, typeTag } val foo = new { def bar = 1 } def getMethods[T: TypeTag](t: T) = typeTag[T].tpe.decls getMethods(foo) // Contains bar 

If you can't use TypeTag (maybe because you can't make API changes), then you're probably best off using the Java reflection API. The Scala reflection API is generally designed to use type information, so it may not work for you if you only know the type is AnyRef.

Read More

Tuesday, November 7, 2017

How to get all objects from WINDOW (added from another classes)

Leave a Comment

I am working with specific program. It has "main window" (a.k.a. "form") where another extensions(protected dll, without access to their source code) can add some objects (texts, labels and etc..) in that window.

How can I access all the objects which is added on that "form" ?

here i example of typical extension:

.... namespace ProgramName.Extensions {      public class MyExtensionName : ProgramName.ExtensionBase{           //here goes typical codes to add things to "form" window,like:          Draw.Arrow(MainFormObject, ArrowColor, ArrowWidth)      }  } 

what code I can use to access all "add"-ed elements , from other, anonymous/inaccessible classed? Is there any "reflection" or any solution?

3 Answers

Answers 1

Adding some objects on a form using a dll requires that the form itself be referenced as an accessible member using something like:

 Assembly assembly = Assembly.LoadFile("C:\\test.dll"); Type type = assembly.GetType("test.dllTest"); Form form = (Form)Activator.CreateInstance(type); 

Then add:

form.Controls.Find(); 

If it is the current form, then on Load method use:

 private void Form_Load(object sender, EventArgs e)     {       this.Controls.Find("name",true)       // OR       foreach(Control c in this.Controls)         if(c.Name == Name)             //Do something...     } 

Answers 2

You can try this

foreach (Control ctrl in this.Controls) {     if (ctrl .GetType().GetProperty("Text") != null)     {         // code here                 } } 

Answers 3

protected dll, without access to their source code

  • These controls sound like COM/OLE/ActiveX:
  • You can access them, as long as you find the code wherein the Main form(The host program) they are maintained.
  • You can try search those controls' keywords in your project code to locate the relevant codes.
  • Including those DLLs into your project reference would provide you the chance to inspect keywords from DLLs.
  • Search the usage of these DLLs and find the code place you want to work with and do your things there.

Example how to get keywords out of DLLs:

enter image description here

Read More

Monday, May 15, 2017

Java reflection handling library changes

Leave a Comment

Ok so I have an Android app and I started creating an addon system for the app so developers can code content providers that the app can then use to generate different content, I will not go through the whole procedure but everything works fine like so:

1) I created a library called com.myaddonlib that I imported in my project in this library there is an interface and different objects.

2) Now a developer can create a simple Java project on his end, import the library com.myaddonlib, and implement the interface on his main class which have methods that return different objects from the library.

3) Back on the android app, I can load the .jar file created by the developer (after the classes.dex is added to the jar file) and with the android DexClassLoader I can load the implemented interface like so :

DexClassLoader classloader = new DexClassLoader(jarFilePath, tempDirectory, null, context.getClass().getClassLoader());      Class classToLoad = classloader.loadClass("com.apackage.Addon"); 

where Addon is the class created by the addon developer that implements the interface from the library residing in a package named com.apackage. I can then cast the interface from the library com.myaddonlib to a new instance of classToLoad and call the functions that the addon developer implemented.

Now here is the issue lets say I decided to update the addon library and remove one of the variables from a class, meaning that the addon's class is now different from the class in the updated library (used in the app). Even when the changed variable is not used something causes the app to crash without any error. Just the fact that both classes are different (even when the only difference is just a missing variable ) causes something to malfunction. Now this is not an easy procedure to explain so I would understand that given my bad english some have trouble following. My issue is that I need to know how to avoid this crash due to the change of the library on one of both ends. And also how java treats object changes in a situation like this

1 Answers

Answers 1

My solution does not solve the problem, but instead makes sure it will never happen. The problem you are describing resembles the classic server-client problem. You have a server (in your case the app you are developing) and clients (the addons that are written by the developers). You can define an interface with many functions and pass data in binary structures. This would be more efficient from a traffic/parsing perspective, however whenever you change the API on the server you will have to update all the clients (or else crashes or other issues might occur).

So to solve this problem on the server-client many choose to use HTTP calls with JSON objects that describe the data. Although this way is less efficient, it allows adding APIs and supporting many client versions at the same time.

Using this approach in Android is quite simple. Define an API with two functions and a single interface:

public String sendDataToLibrary(String jsonString) {    // Parse data, perform operation and return a JSON string as the result }  public interface GetDataFromLibrary {    String onDataFromLibrary(String jsonString); }  public void init startLibrary(GetDataFromLibrary callback) {    // Set callback in library and call it whenever you have data that needs to be sent out from the library asynchronously  } 

As you can see, if you implement this interface, you can pass any data around between the library and addons and it will never change so no crashes would occur. An improvement can be to force passing version number to allow the library to support multi-versioning).

Read More

Monday, April 25, 2016

getDeclaredConstructor on an interface?

Leave a Comment

The javadoc for Class::getDeclaredConstructor (http://docs.oracle.com/javase/8/docs/api/java/lang/Class.html#getDeclaredConstructor-java.lang.Class...-) says:

Returns a Constructor object that reflects the specified constructor of the class or interface represented by this Class object. [emphasis mine]

Since you can't declare a constructor for an interface, what could it mean to return a "specified constructor" of an interface?

I tried it on Runnable.class and got NoSuchMethodException. Is there a case where getDeclaredConstructor will work on an interface? Or is this language in the javadoc just an error? Or does it mean something other than how I'm interpreting it?

3 Answers

Answers 1

A call to Class.getConstructor will result in a call to Class.privateGetDeclaredConstructors to retrieve all declared constructors. The matching constructor is selected from that list:

private Constructor<T>[] privateGetDeclaredConstructors(boolean publicOnly) {     ...     // No cached value available; request value from VM     if (isInterface()) {         @SuppressWarnings("unchecked")         Constructor<T>[] temporaryRes = (Constructor<T>[]) new Constructor<?>[0];         res = temporaryRes;     } else {         res = getDeclaredConstructors0(publicOnly);     }     ...     return res; } 

(I removed part of the code which deals with cached constructors).

So for interfaces the constructor list is always empty and a NoSuchMethodException will always be thrown.

Answers 2

I don't consider this an error in javadoc. Class object can represent class or interface, there is no error in that statement.

If you're using reflection and explicitly ask for specific elements, you have to make sure that elements with the identification specified in the reflective calls exist. If you're asking for a specific constructor that does not exist in the provided Class, you'll get NoSuchMethodException be it a class for an interface, primitive type, array, void or simply a class that does not declare such a constructor.

Above I emphasised the word specific. For example, in a similar method that returns all constructors for a Class (Class::getDeclaredConstructors) interfaces are handled appropriately:

Returns an array of Constructor objects reflecting all the constructors declared by the class represented by this Class object. These are public, protected, default (package) access, and private constructors. The elements in the array returned are not sorted and are not in any particular order. If the class has a default constructor, it is included in the returned array. This method returns an array of length 0 if this Class object represents an interface, a primitive type, an array class, or void.

Answers 3

This is the use case I can think of: on a reflection-based application, a method receives a Class argument. The method needs to construct an instance of the given class, so it checks for the declared constructors. This is a simplified example that just prints the constructors on four different use cases:

  1. A class instance invoking getClass()
  2. An interface instance invoking getClass()
  3. An actual ClassX.class
  4. An actual InterfaceY.class

    public class Testctor {      public static void main(String[] args) {         new Testctor().testGetDeclCtors();     }      public void testGetDeclCtors() {         Class1 c1 = new Class1(4);         printClassInfo(c1.getClass());          I2 i2 = c1;         printClassInfo(i2.getClass());          printClassInfo(Class1.class);          printClassInfo(I2.class);     }      private void printClassInfo(Class<?> claz) {         Constructor<?> ctor = null;         try {             ctor = claz.getDeclaredConstructor();         } catch (NoSuchMethodException | SecurityException e) {         }         System.out.println(claz+": "+ctor);     } }  interface I2 { }  class Class1 implements I2 {     public Class1() {     }      public Class1(int x) {     } } 

This prints these results:

class test.Class1: public test.Class1() class test.Class1: public test.Class1() class test.Class1: public test.Class1() interface test.I2: null 
Read More