2016-05-10 7 views
2

Ich schreibe eine Anwendung, die Verwendung von Klassen definiert durch die folgende Schnittstelle macht:Einfacher Injector Bedingte Register mit den Delegierten

public interface ICredentialProvider 
{ 
    string GetUsername(); 
    string GetPassword(); 
} 

können Dies geschieht so, Methoden, um den Benutzername/Passwort, anstatt es abzurufen aufgerufen werden statisch im Speicher gehalten und in der code/config-Datei definiert werden.

Derzeit in Entwicklung Ich bin mit dieser sehr einfachen Implementierung:

public class FakedCredentialProvider : ICredentialProvider 
{ 
    private readonly string _username; 
    private readonly string _password; 

    public FakedCredentialProvider(string username, string password) 
    { 
     _username = username; 
     _password = password; 
    } 

    public string GetUsername() 
    { 
     return _username; 
    } 

    public string GetPassword() 
    { 
     return _password; 
    } 
} 

... die zwei Strings im Konstruktor akzeptiert. Zukünftige (tatsächliche) Implementierungen von ICredentialProvider müssen wahrscheinlich bestimmte Zeichenfolgen für die Verbindung mit dem entsprechenden externen Passwortspeicher oder -dienst (oder möglicherweise beiden; an dieser Stelle im Projekt, die unklar ist) akzeptieren.

Außerdem verwendet das Projekt mehrere Instanzen von ICredentialProvider für die verschiedenen Konten, zu denen es eine Verbindung herstellen muss (z. B. SharePoint, ActiveDirectory und Windows Graph).

Zu diesem Zweck Ich weiß, wie über einen Delegierten registrieren:

container.RegisterWebApiRequest(() => 
    new FakedCredentialProvider(fakedSharePointUsername, fakedSharePointPassword)); 

... Und wie man bedingt registrieren ...

container.RegisterConditional(typeof(ICredentialProvider), typeof(FakedCredentialProvider), 
     context => 
     context.Consumer.Target.Name.ToLower().Contains("sharepoint") 
    ); 

... Aber nicht, wie das kombinieren zwei.

Wie kombiniert man diese beiden Ansätze? Oder alternativ: Gibt es ein besseres Design für solche Situationen?

+1

denke ich, ein besser Design würde sein, verschiedene Schnittstellen für jeden Credential-Provider zu erstellen. Der Grund dafür ist, dass eine Klasse, die einen Sharepoint-Credential-Provider verwendet, nicht korrekt mit einem Active-Directory-Credential-Provider funktioniert. Die Credential Provider sind nicht austauschbar, daher differenzieren Sie sich dafür in Ihrem Design. – Maarten

+0

@Maarten Nun, die zurückgegebenen Werte sind nicht austauschbar, aber der externe Vertrag ist. Nicht nur das, sondern die Anmeldeinformationen werden letztendlich alle in Cyberarks Password Vault oder einem Webdienst gespeichert, so dass der SharePoint- und AD-Zugriff (z. B.) CyberarkPasswordVaultCredentialProvider: ICredentialProvider verwenden kann. Ich habe das Gefühl, wenn du sagst, dass _das_ nicht als austauschbar gilt (extern sind sie identisch und teilen konkrete Implementierungen mit), wären SOLID-gesteuerte Schnittstellen niemals angemessen. –

+0

Warum haben Sie den ICredentialProvider überhaupt? Warum injizieren Sie diese Anmeldeinformationen nicht in die Klasse, die sie direkt benötigt (vorausgesetzt, diese Werte sind keine Laufzeitwerte, sondern natürlich Konfigurationswerte). – Steven

Antwort

3

Ich bin nicht sicher, ob ich Ihre Einschränkungen und Design voll und ganz verstehen, aber die Art und Weise Registrierung von bedingt Delegierten zu tun, ist eine der RegisterConditional Überlastungen verwenden, die ein Registration Objekt akzeptiert:

var container = new Container(); 
container.Options.DefaultScopedLifestyle = new WebApiRequestLifestyle(); 

container.RegisterConditional(typeof(ICredentialProvider), 
    Lifestyle.Scoped.CreateRegistration(() => new FakedCredentialProvider(user, pwd), 
     container), 
    c => c.Consumer.Target.Name.ToLower().Contains("sharepoint")); 
+0

Entschuldigung, wenn ich nicht klar über das Design war; manchmal fällt es mir schwer, meine Gedanken im Text zu lesen. Ich schätze die Antwort, Steven. –