lundi 16 juillet 2018

calling getConstructor without hard-coding the parameter types in a Class[]

Where I'm At

I've almost fully implemented Dependency Injection, the Factory Pattern, and a properties file into my code. right now I'm in the testing phase and I found an error because I misunderstood how foo.getConstructor worked. I understand now that it requires a Class[] as an argument to specify which constructor you actually want to get via the types.

My Problem

is I'm trying to eliminate coupling and by having to hard-code in the parameter types to get the constructor I want, its causing coupling to emerge. I saw some stuff about the default constructor but I think that calls the standard no-arg constructor. I want to call the only constructor in my class but it is a multi argument constructor. How do I get this constructor without specifying specific class types. I tried passing in Object as a type but It didn't accept the super-type so it must only accept the actual type, not a super or sub type. If there is another, non type specific way to do this I'm all ears. Getting the # of arguments through the get-fields method introduces dependency between the constructor parameters and the fields and also requires the fields to be public. I don't want either of those. I do have setters and getters but I don't know how I'd use them dynamically (each class will have different ones).

Example of the constructor:

//this class is relfectively gotten through the properties file in the 
//ObjectFactory. the argument names are the same as the fields
SalesRep(String name, String number, String email, String company, ArrayList<SalesRep> matched_with) {
    this.name = name;
    this.company = company;
    this.matched_with = matched_with;
    this.email = email;
    this.number = number;
}

Example code of where the constructor is gotten:

//factory pattern instantiation
ObjectFactory(String[] firstLineArray){
    //loading in properties and parameter names so I can dynamically create
    //class instances based on CSV files
    this.firstLineArray = firstLineArray;
    Properties prop = new Properties();
    try {
        prop.load(ObjectFactory.class.getResourceAsStream("config.properties"));
    } catch (IOException e) { e.printStackTrace(); }
    this.MethodMap = new HashMap<>();
    this.FieldMap = new HashMap<>();
    //dynamically loading in a class that implements Objectimplementation
    //it uses a properties file named "properties.config" to do so.
    try {
        Class<? extends ObjectImplementation> Classtouse = Class.forName(prop.getProperty("ObjectImplementation")).asSubclass(ObjectImplementation.class);

The field dependency problem

        //get the length of the list of constructor arguments using the 
        //fields BUT THIS INTRODUCES UNWANTED DEPENDENCIES
        int L = Classtouse.getFields().length;
        //specify the dynamic length of the constructor
        Class[] classes = new Class[L];
        //set every element to Object.class to make the data generic (it can be casted later)
        for (int i = 0; i < (L); i++) {
            classes[i] = Object.class;
        }
        Classtouse.getConstructor(classes).setAccessible(true);
//this throw a noSuchMethod exception here because the explicit types 
//aren't Object they're a combination of Object sub-types
        this.constructor = Classtouse.getConstructor(classes);
//GOAL: do stuff with the constructor here

The Goal

is to be able to dynamically call the one constructor for every class that implements Object Implementation so that I can finally have a fully decoupled system here. I want to be able to dynamically specify the entire class, including the constructor. If I hard-code the parameter types then any implementing class will have to have the same constructor (kinda defeats the purpose of all this stuff).

What I've done/Am doing/Will do

I scoured google (useless) and searched through stack overflow (more useful) and I updated quite a bit of stuff before posting. I've ran the code above and gotten NoSuchMethod Exception. I'm going to try to keep experimenting (that's how I code when I don't know what to do). Any help is much appreciated.





Aucun commentaire:

Enregistrer un commentaire