Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support for creating components using constructor via dependency injection #1264

Open
wants to merge 1 commit into
base: master
Choose a base branch
from

Conversation

TalosDx
Copy link

@TalosDx TalosDx commented Jul 28, 2020

Details here
Sorry about my english

@SchweinchenFuntik
Copy link
Contributor

SchweinchenFuntik commented Jul 28, 2020

Your option gives priority to non-native DI. It also becomes unclear where we got the instance from (from which DI).
This leads to confusion and makes it harder to understand the instance dependencies.

@TalosDx
Copy link
Author

TalosDx commented Jul 28, 2020

dicontainer property of the FX class in which the changes take place.
Yes, this gives priority to the non-native di, if dicontainer is not null
If we need priority to the native di, then we need to register it as a dicontainer, otherwise we cut the capabilities of any other di in favor of the native one (isn't good)

@SchweinchenFuntik
Copy link
Contributor

for other DIs you need to use:

val MyView : View() {
    val helloService: HelloService by di()
}

What are the reasons for TornadofX DI behavior change?

@TalosDx
Copy link
Author

TalosDx commented Jul 28, 2020

My idea is to make it possible to use di through the constructor, ideally it should be for the native di too.
If you have ideas better suggest

@SchweinchenFuntik
Copy link
Contributor

SchweinchenFuntik commented Jul 28, 2020

Yes, but this requires some serious work on the concept rather than changing a few lines (maybe it should be done in Tornadofx 2.0).

Where is your constructor with parameters here? You just get an instance from your DI scope, nothing has changed on the Tornadofx side.

Also, will your DI take into account the differences between View and Fragment ?

@TalosDx
Copy link
Author

TalosDx commented Jul 28, 2020

Lunch is over, I'll write it in the evening

@edvin
Copy link
Owner

edvin commented Jul 28, 2020

If we do a major rewrite of the dependency injection mechanism in TornadoFX, I suggest making third party injection frameworks a first class citizen perhaps? TornadoFX could ship with a simple mechanism like it has now, with the ability to plug in a third party extension for all the roles the native mechanism is used for.

@SchweinchenFuntik
Copy link
Contributor

SchweinchenFuntik commented Jul 28, 2020

Well, there is one option for automatic inject through the constructor (through the same reflection). And it shouldn't break old code.

The logic is simple, we check the parameters of the primary constructor and look for the necessary dependencies in the scope.

The problem can only cause recursive component dependencies

Today or tomorrow I will try to provide the code.

EDIT: To integrate with other DI, need to think about how to design it better and work out the details

@SchweinchenFuntik
Copy link
Contributor

SchweinchenFuntik commented Jul 29, 2020

https://github.com/SchweinchenFuntik/tornadofx/blob/DI_constructor_injection/src/main/java/tornadofx/FX.kt#L437

a big drawback of the approach - parameters with types that cannot be injected can be passed to the constructor

simple sample:

class TView(private val tController: TController, val personModel: PersonModel) : View("Constructor Injection") {
    override val root = vbox(10) {
        paddingAll = 5
        textfield(personModel.name)

        listview(tController.persons) { cellFormat { text = it.name } }
    }
}

class TController(val personModel: PersonModel) : Controller() {
    val persons = observableListOf(
            Person().apply { name = "Bob" },
            Person().apply { name = "Vanga" }
    )

    init {
        personModel.item = persons.first()
    }
}

class Person {
    val idProperty = SimpleIntegerProperty(0)
    var id by idProperty

    val nameProperty = SimpleStringProperty("")
    var name by nameProperty
}

class PersonModel : ItemViewModel<Person>() {
    val id = bind(Person::idProperty)
    val name = bind(Person::nameProperty)
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

3 participants