8

Kullanıcı girdisine bağlı olarak birden fazla enjeksiyon işlemini desteklemek için çalışma zamanında Guice enjeksiyonlarını değiştirebilmeyi isterim.Çalışma zamanında Guice bağlarının değiştirilmesi

public interface IDao { 
    public int someMethod(); 
} 

public class DaoEarth implements IDao { 
    @Override 
    public int someMethod(){ ... } 
} 

public class DaoMars implements IDao { 
    @Override 
    public int someMethod(){ ... } 
} 

public class MyClass { 
    @Inject 
    private IDao myDao; 

    public int myMethod(String domain) { 
     //If Domain == Earth, myDao should be of the type DaoEarth 

     //If Domain == DaoMars, myDao should be of the type DaoMars 
    } 
} 

Kendi Sağlayıcı yazmayı düşünüyorum, ama ben zamanında benim bağları değiştirmek o sağlayıcı nasıl kullanılacağını bilmiyorum: Bu benim başarmak istiyoruz şeydir. Herhangi bir giriş hoşgeldiniz ve takdir :)! Burada şu anda ile geldi ne

Update ben istediğim kadar hoş değil, bu yüzden hala geribildirim arıyorum

public class DomainProvider { 
    @Inject @Earth 
    private IDaoProvider earthDaoProvider; 

    @Inject @Mars 
    private IDaoProvider marsDaoProvider; 

    public IDaoProvider get(Domain domain){ 
     switch (domain){ 
      case EARTH: 
       return earthDaoProvider; 
      case MARS: 
       return marsDaoProvider; 
     } 
    } 

    public IDaoProvider get(String domain){ 
     Domain parsedDomain = Domain.valueOf(domain.toUpperCase()); 
     return get(parsedDomain); 
    } 
} 

//MarsDaoProvider would be equivalent 
public class EarthDaoProvider implements IDaoProvider { 
    @Inject @Earth 
    private IDao earthDao; 

    public IDao getDao() { 
     return earthDao; 
    } 
} 

This means that in "MyClass", I can do: 
public class MyClass { 
    @Inject 
    private DomainProvider domainProvider; 

    public int myMethod(String domain) { 
     IDaoProvider daoProvider = domainProvider.get(domain); 
     IDao dao = daoProvider.getDao(); 

     //Now "dao" will be of the correct type based on the domain 
    } 
} 

//Of course elsewhere I have the bindings set like 
bind(IDao.class).annotatedWith(Earth.class).to(EarthDao.class); 
+0

Yardımlı enjeksiyonun bana nasıl yardımcı olabileceğinden tam olarak emin değilim. Yardımlı enjeksiyonun, sağlanan parametrelerle enjekte edilen parametreleri birleştirmenize izin vermesini sağlarım, ancak durumum için bunun nasıl çalışacağından tam olarak emin değilim. – Nepoxx

cevap

12

Sürüm olduğu gibi neredeyse mükemmel: Yazdığınız koda dayalı olarak bir veya diğerini döndüren ve yardımlı enjeksiyona veya buna benzer bir şeye ihtiyaç duymayan bir çeşit nesne enjekte etmeniz gerekecek. Yani Demirbaş bazı atlayabilirsiniz, şunları söyledi: bu durumda

public class DomainProvider { 
    // Just inject Providers directly without binding them explicitly. 
    @Inject @Earth Provider<IDao> earthDaoProvider; 
    @Inject @Mars Provider<IDao> marsDaoProvider; 

    public Provider<IDao> get(Domain domain){ 
     switch (domain){ 
      case EARTH: 
       return earthDaoProvider; 
      case MARS: 
       return marsDaoProvider; 
     } 
    } 

    public Provider<IDao> get(String domain){ 
     Domain parsedDomain = Domain.valueOf(domain.toUpperCase()); 
     return get(parsedDomain); 
    } 
} 

Kişisel Sınıfım tamamen aynı olurdu. Burada Provider, tek yöntemli jenerik arabirim com.google.inject.Provider veya uzandığı eşdeğer javax.inject.Provider eşdeğeridir. the relevant Guice wiki topic Guice Sağlayıcıları hakkında daha fazla bilgi edinin. Temel olarak

bind(IDao.class).annotatedWith(Earth.class).to(EarthDao.class); 
// You can now inject "@Earth IDao" and also "@Earth Provider<IDao>". 

, ek bir çalışma ile önemli bir Foo (bir sınıf, sağlayıcı, @Provides yöntem veya örneğine) kullanarak, automatically get to inject either a Foo or Provider<Foo> spesifiktir. Sağlayıcılar, istediğiniz her şey için get numaralı telefona yapılan her çağrıyla yeni bir örnek almanızı sağlamak için harika bir yoldur; Orijinal belgenizle, enjekte ettiğiniz herhangi bir DomainProvider için daima EarthDao veya MarsDao örneğini alırsınız. (@Singleton gibi kapsamlı bir bağlayıcınız varsa, Guice de buna saygı gösterir; Sağlayıcı, yalnızca eski bir Java başvurusunu yeniden kullanmak yerine Guice'nin dahil olmasına izin verir.)

Bu, özel EarthDaoProvider ve MarsDaoProvider öğelerinizi atlayamadığınız sürece gerçekten herhangi bir harici başlatmayı gerçekleştirmeniz gerekir — bu noktada muhtemelen bind(EarthDao.class).toProvider(EarthDaoProvider.class) numaralı telefonu aramadan daha iyi olabilirsiniz. Böylece, EarthDao doğrudan enjekte edilirken de hazırlık yapılır. Ayrıca, DomainProvider'ın, uygun Sağlayıcıda get numaralı telefonu arayarak doğrudan bir IDao örneğini döndürebilir ve her seferinde yeni bir örnek olacağından emin olabilirsiniz.

+0

Bu mükemmel bir cevap, açıklama/bağlantılar için bonus puanları :) – Nepoxx

+0

"Sağlayıcılar," get "için her çağrıda yeni bir örnek almanızı sağlamak için de harika bir yoldur - ne olursa olsun, bir singleton örneği almak istersek 'get' için her çağrıda yeni bir örneğin? – PapaSierra

+1

@PapaSierra Bunu Guice'de yapılandırırsanız, alacağınız şey budur; Guice'de bu şekilde yapılandırılmasını istersiniz, böylece başka bir tüketiciden farklı bir örnek alamazsınız. Benim önerim, bir Sağlayıcı yerine tek bir örnek enjekte ederek, Guice'deki yapılandırmadan bağımsız olarak her zaman bu örneği döndürmenizdir. –

İlgili konular