Your solution seems to be great.
I personally found another way to manage to inject dependencies once, and
transparently, using a ProxyInjector.
This factory provides a method that creates a proxy object for the
requested dependencies.
Dependencies are injected only when it's necessary.
For each dependency, a get property is added to a proxy object.
When using this property, the proxy object loads the dependency, then
replaces this get property by a direct reference to the dependency.
So, the first time you call a dependency from the proxy object, you call a
method that loads the dependency then returns it.
Then, the next time you call this dependency from the proxy object, you
have a direct access to it, without computing anything.
Example :
function factory ( $http, $q, proxyInjector )
{
var proxy = proxyInjector(
'DependencyA',
'DependencyB',
'DependencyC' );
var MyService = {
getA : function ( id )
{
return proxy.DependencyA.get( id );
},
createB : function ()
{
return new proxy.DependencyB();
},
computeC : function ( a, b )
{
return proxy.DependencyC( a, b );
},
}
}
module.factory( 'MyService', [ '$http', '$q', 'proxyInjector', factory ] );
I put this Proxy Injector in a GitHub repository. Feel free to use it.
https://github.com/antoine-agthe/AngularJS-ProxyInjector
Le jeudi 29 mai 2014 11:48:24 UTC-4, Eric Eslinger a écrit :
>
> I have a similar problem in my janky homegrown ORM - bidirectional
> parent-child has many and belongs to many type relationships are annoying
> at times.
>
> Personally, I do it by having an abstract base class that all the models
> in my ORM derive from. In the concrete class declaration, I do something
> like Model.registerChildConstructor('document', this). I use the
> coffeescript form of classical inheritance.
>
> That way I can do stuff like Model.findWithType('document', 2), or new
> Model.childConstructors.document(). (I know - I should capitalize document
> in that case, but I'm cheating because the "name" of the object is
> lowercased and identical to the name of the table where I store the data,
> which makes life easer). So when I get a chunk of data from my API, I can
> do a data.map (v)->Model.findWithType(v.type, v.id) sorta thing.
>
> I don't need to inject Document into model, because I already have access
> to the constructor function, and in the subclasses, I can do
> Model.findWithType just fine (since I have to inject the ABC in order to
> inherit from it). My opinion is that circular dependencies are an example
> of flawed code most of the time and should be avoided. Then again, I'm just
> bypassing the angular complaints by using a string instead of a real object
> to inject.
>
> e
>
>
> On Thu, May 29, 2014 at 2:47 AM, Antoine AGTHE <[email protected]
> <javascript:>> wrote:
>
>> Hi Guyz,
>>
>> I got a typical cross dependency case that I solved, but I don't like my
>> solution, as it's not that much elegant.
>> The situation is the following:
>>
>> I have ElementA,and ElementB, that are "classes" (that can be
>> instantiated).
>> ElementA instance holds the ID of a ElementB object, and ElementB holds
>> a list of ElementA IDs.
>> It's like ElementB is a parent of ElementA objects, and an ElementA
>> object can have only one parent.
>>
>> I have ElementAProvider and ElementBProvider, that are objects that can
>> retrieve ElementA and ElementB data from a RESTful service.
>> These service returns instances of class ElementA and ElementB.
>>
>> To make my objects easier to use, I added getParent() to ElementA
>> prototype, and getChildren() to ElementB prototype, so they returns
>> instances of the parent, or the children, instead of just the ID. These
>> methods use ElementAProvider et ElementBProvider to get these instances.
>>
>> ElementA.prototype = {
>> getParent : function ()
>> {
>> return ElementBProvider.get( this.parentId );
>> }
>> }
>>
>> ElementB.prototype = {
>> getChildren : function ()
>> {
>> return ElementAProvider.getSeveral( this.childrenIds );
>> }
>> }
>>
>> The problem is, that when I add my factories to my module, I have to
>> define my dependencies :
>>
>> module.factory( 'ElementA' , [ '$http', '$q', 'ElementBProvider',
>> factoryElementA ] );
>> module.factory( 'ElementB' , [ '$http', '$q', 'ElementAProvider',
>> factoryElementB ] );
>> module.factory( 'ElementAProvider', [ '$http', '$q', 'ElementA' ,
>> factoryElementAProvider ] );
>> module.factory( 'ElementBProvider', [ '$http', '$q', 'ElementB' ,
>> factoryElementBProvider ] );
>>
>> So ElementA needs ElementBProvider, that needs ElementB, that needs
>> ElementAProvider, that needs ElementA.
>>
>> To solve that, I use $injector to manually get dependencies just before
>> using them.
>>
>> function factoryElementA ( $http, $q, $injector )
>> {
>> var ElementBProvider = null;
>>
>> function _getDependencies ()
>> {
>> if ( ElementBProvider == null ) $injector.get( 'ElementBProvider'
>> );
>> }
>>
>> function ElementA ( /* … */ )
>> {
>> // …
>> }
>>
>> ElementA.prototype = {
>> getParent : function ()
>> {
>> _getDependencies();
>> return ElementBProvider.get( this.parentId );
>> }
>> }
>> }
>>
>> module.factory( 'ElementA', [ '$http', '$q', '$injector', factoryElementA
>> ] );
>>
>> It works, but each time I need to use my dependencies, I have to check
>> them.
>> Is there another smarter way to do it ?
>>
>> --
>> You received this message because you are subscribed to the Google Groups
>> "AngularJS" group.
>> To unsubscribe from this group and stop receiving emails from it, send an
>> email to [email protected] <javascript:>.
>> To post to this group, send email to [email protected]
>> <javascript:>.
>> Visit this group at http://groups.google.com/group/angular.
>> For more options, visit https://groups.google.com/d/optout.
>>
>
>
--
You received this message because you are subscribed to the Google Groups
"AngularJS" group.
To unsubscribe from this group and stop receiving emails from it, send an email
to [email protected].
To post to this group, send email to [email protected].
Visit this group at http://groups.google.com/group/angular.
For more options, visit https://groups.google.com/d/optout.