12

Şartlı çözümleme şu anda anlamadığım en son şey. Bağımlılık Enjeksiyon Birimi - Koşullu Çözümleme

public interface IAuthenticate{ 
    bool Login(string user, string pass); 
} 

Şimdi iki kimlik doğrulama türü vardır:

biz bir arayüz IAuthenticate var düşünelim. birlik config

Heyecan auth

public class TwitterAuth : IAuthenticate 
{ 
    bool Login(string user, string pass) 
{ 
    //connect to twitter api 
} 

} 

Facebook Auth

public class FacebookAuth: IAuthenticate 
{ 
    bool Login(string user, string pass) 
{ 
    //connect to fb api 
} 

} 

kaydedilmesi türleri:

unityContainer.RegisterType<IAuthenticate, TwitterAuth>(); 
unityContainer.RegisterType<IAuthenticate, FacebookAuth>(); 

bizim denetleyicisi DI'nin aracılığıyla nesneleri enjekte:

Farklı kimlik doğrulama türleri için hangi nesnenin çözümlenmesi gerektiğini birlik tam olarak nasıl bilecek? Bu durumda koşullu çözümleme nasıl yapabilirim?

Arkadaşımla konuştum ve bu durumun yanlış bir tasarım olduğu ortaya çıktığında açıkladı, ama bu sadece fabrika modelidir.

+0

Arkadaşınız haklı olabilir. [Liskov İkame Prensibi] 'ni ihlal etmediğinizde yakından bakın (https://en.wikipedia.org/wiki/Liskov_substitution_principle).Eğer 'IAuthenticate'' uygulamaları birbiri ile uyumlu değilse (yani "AuthenticateController" gibi bir tüketici yanlış uygulamayı gerçekleştirirse doğru şekilde çalışmayacaktır), LSP'yi ihlal ediyorsunuz demektir. Bu durumda çözüm genellikle her bir uygulamaya kendi soyutlamasını verir. – Steven

cevap

32

Bunu çözmenin basit bir yolu strategy pattern ile. Tasarımı değiştirmeden giriş sağlayıcıları ekleyebileceğinizi veya kaldırabileceğinizi unutmayın - sadece DI konfigürasyonunu değiştirmeniz gerekir.

Arayüzler

public interface IAuthenticate{ 
    bool Login(string user, string pass); 
    bool AppliesTo(string providerName); 
} 

public interface IAuthenticateStrategy 
{ 
    bool Login(string providerName, string user, string pass); 
} 

kimlik doğrulaması Sağlayıcıları

public class TwitterAuth : IAuthenticate 
{ 
    bool Login(string user, string pass) 
    { 
     //connect to twitter api 
    } 

    bool AppliesTo(string providerName) 
    { 
     // I used the type name for this example, but 
     // note that you could use any string or other 
     // datatype to select the correct provider. 
     return this.GetType().Name.Equals(providerName); 
    } 
} 

public class FacebookAuth: IAuthenticate 
{ 
    bool Login(string user, string pass) 
    { 
     //connect to fb api 
    } 

    bool AppliesTo(string providerName) 
    { 
     return this.GetType().Name.Equals(providerName); 
    } 
} 

Strateji

public class AuthenticateStrategy: IAuthenticateStrategy 
{ 
    private readonly IAuthenticate[] authenticateProviders; 

    public AuthenticateStrategy(IAuthenticate[] authenticateProviders) 
    { 
     if (authenticateProviders == null) 
      throw new ArgumentNullException("authenticateProviders"); 

     this.authenticateProviders = authenticateProviders; 
    } 

    public bool Login(string providerName, string user, string pass) 
    { 
     var provider = this.authenticateProviders 
      .FirstOrDefault(x => x.AppliesTo(providerName)); 

     if (provider == null) 
     { 
      throw new Exception("Login provider not registered"); 
     } 

     return provider.Login(user, pass); 
    } 
} 

Birlik Kayıt

// Note that the strings used here for instance names have nothing 
// to do with the strings used to select the instance in the strategy pattern 
unityContainer.RegisterType<IAuthenticate, TwitterAuth>("twitterAuth"); 
unityContainer.RegisterType<IAuthenticate, FacebookAuth>("facebookAuth"); 
unityContainer.RegisterType<IAuthenticateStrategy, AuthenticateStrategy>(
    new InjectionConstructor(
     new ResolvedArrayParameter<IAuthenticate>(
      new ResolvedParameter<IAuthenticate>("twitterAuth") 
     ), 
     new ResolvedArrayParameter<IAuthenticate>(
      new ResolvedParameter<IAuthenticate>("facebookAuth") 
     ) 
    )); 

Kullanım

private readonly IAuthenticateStrategy _authenticateStrategy; 

public AuthenticateController(IAuthenticateStrategy authenticateStrategy) 
{ 
    if (authenticateStrategy == null) 
     throw new ArgumentNullException("authenticateStrategy"); 

    _authenticateStrategy = authenticateStrategy; 
} 



// login with twitter 
public virtual ActionResult Twitter(string user, string pass) 
{ 
    bool success = 
      _authenticateStrategy.Login("TwitterAuth", user, pass); 
} 



// login with fb 
public virtual ActionResult Facebook(string user, string pass) 
{ 
    bool success = 
      _authenticateStrategy.Login("FacebookAuth", user, pass); 
} 
3

Birlik sizin yardımınız olmadan olmaz. Artık doğrudan AuthenticateController içine ıauthenticate örneğini enjekte etmek isteyeceksiniz

unityContainer.RegisterType<IAuthenticate, TwitterAuth>("Twitter"); 
unityContainer.RegisterType<IAuthenticate, FacebookAuth>("Facebook"); 

: Size ıauthenticate türlerini kayıt bir isim verebilir. (Eğer sıkı bir DI tarzı gibi eğer)

myContainer.Resolve<IAuthenticate>("Twitter"); 

veya sizin için bunu yapan bir Fabrikası enjekte edeceğiz: Doğru birlik dışına bir koşulu temel istediğiniz örneğini alırsınız ya.