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.

Reply via email to