samber / do

⚙️ A dependency injection toolkit based on Go 1.18+ Generics.
https://pkg.go.dev/github.com/samber/do
MIT License
1.71k stars 67 forks source link

Support `interface` in `As`/`InvokeAs` #81

Open d-enk opened 2 months ago

d-enk commented 2 months ago

I suggest using something like:

func canCast[FROM, TO any](soft bool) bool {
    var from FROM
    anyFrom := any(from)

    if anyFrom == nil { // check for interface by reflect
        typeFrom := reflect.TypeOf(&from).Elem()
        typeTo := reflect.TypeOf((*TO)(nil)).Elem()

        toInterface := typeTo.Kind() == reflect.Interface

        return toInterface && typeFrom.Implements(typeTo) ||

            // interface -> not interface - maybe false positive when real FROM not TO
            soft && !toInterface && typeTo.Implements(typeFrom)
    }

    _, ok := anyFrom.(TO)

    return ok
}

instead simply:

var from FROM
_, ok := any(from).(TO)

For As just call canCast[Initial, Alias] https://github.com/samber/do/blob/1998a7a1b1a618eed087c91bc4932934355d5477/di_alias.go#L25-L26

For InvokeAs apparently need getInstanceType() reflect.Type method https://github.com/samber/do/blob/1998a7a1b1a618eed087c91bc4932934355d5477/service.go#L131-L133

d-enk commented 2 months ago

soft flag includes checking whether TO type (not interface) can be in FROM interface looks like a very rare case, but still happens

in case of As you can rely on the provider's error https://github.com/samber/do/blob/1998a7a1b1a618eed087c91bc4932934355d5477/service_alias.go#L161-L166