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

Create typescript injector and data binding utils using decorators #43

Closed
doriansmiley opened this issue Aug 28, 2017 · 4 comments
Closed
Assignees

Comments

@doriansmiley
Copy link
Owner

doriansmiley commented Aug 28, 2017

You can use decorators to do DI, scopes, etc. Info on how to build decorators is here: http://blog.wolksoftware.com/decorators-metadata-reflection-in-typescript-from-novice-to-expert-part-4

Better yet there is an IOC framework for typekit. See if you can extend it to provide the decorators for DI in typescript and hook up to function overrides that will work with Lotus injector and scopes. Framework is here: https://www.npmjs.com/package/typescript-ioc

I'd like to include an @bindable decorator that will mixin subject if the object does not extend it, and add the notify call to the setter. See if we could also use @bindable on a public property replacing the public property with a private one, and adding the accessor methods.

@doriansmiley doriansmiley added this to the TypeScript Refactor milestone Aug 28, 2017
@doriansmiley doriansmiley self-assigned this Aug 28, 2017
@doriansmiley doriansmiley changed the title Create typescript injector using decorators Create typescript injector and data binding utils using decorators Aug 30, 2017
@doriansmiley
Copy link
Owner Author

branch created: #43_implementDecorators

@doriansmiley
Copy link
Owner Author

try refactoring the inject function to overwrite the constructor of target and add the following:

if(this.resolveInjections){
            //TODO: move this method to a decorator that sets up this.resolveInjections as an accessor and adds this functionality to the contructor
            this.resolveInjections.forEach(function(value:injectionResolver, index:number){
                var instane:any = this.context.injector.inject(value.type);
                if(instane){
                    this[value.property] = instane;
                }
            }.bind(this));
        }

Then refactor AbstractMediator by removing this code. This allows the @Inject decorator to set up the target with the required code to resolve injections once the constructor is called and the context is available. Also it's probably a good idea to ensure that target has a context attribute somewhere in it's inheritance chain.

If this is not possible create a new decorator called @Injectable that will add the code to the target.

Also see if there is someway to use the injector to map interfaces. Something like:

this.context.injector.mapObject(Lotus.IHttpService, Lotus.HttpService)

This is the last real piece missing as in general you always inject into interface types to avoid restricting yourself to a single inheritance chain.

What I am finding is that the use of decorators adds a fairly substantial amount of code to your libs. As such I would probably not recommend the use of declarative and opt for the imperative use of this.context.injector.inject. Also currently we have to load a polyfill to get type metadata for properties and function parameter. This is a fairly large lib that can be avoided entirely if people opt for the imperative form. Be sure the documentation reflects this and encourages use of the imperative form. The reflect pollyfile can be found here: https://github.com/rbuckton/reflect-metadata. Some good info on the issues with code bloat can be found here: microsoft/TypeScript#4737 and microsoft/TypeScript#2589.

@doriansmiley
Copy link
Owner Author

I was not able to overwrite the constructor within @Inject due to the fact the object's constructor was already defined at that stage. This required me to create the @injectable decorator which does add the required code to the constructor. What's cool is I can add the @injectable decorator to base classes which allows me simply use @inject in sub classes which limits the amount of decorator code that has to be included by the developer. This should also reduce the amount of code in the emitted javascript.

@doriansmiley
Copy link
Owner Author

doriansmiley commented Sep 18, 2017

I was not able to use @bindable on getter or setter functions. Decorating them caused the parameter injection workflow to take place. This means if you set up getter/setter methods on private properties you have to call this.notify manually. Otherwise you can declare any public property as bindable. Perhaps it is possible to set up @bindable on the class and get the original property definitions that way. Something to consider next release.

Also, we cannot map injections to interface definitions. They are dropped by default in the exported lib since they serve no real purpose outside of typescript compiler checking.

Update read me with declarative and imperative examples. for data binding and injection.

Remove decorators from AbstractCommand, ButtonMediator, and AbstractMediator objects. This bloats the code base. Also remove the pollyfill loaded on the button sample application.

Add task to create new sample application that shows how to use decorators.

Remove use of global objects to access framework resources in sample application.

publish release

doriansmiley added a commit that referenced this issue Sep 19, 2017
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

No branches or pull requests

1 participant