2017-04-20 3 views
1

Ich habe eine generische Datenbankklasse geschrieben, die aufgerufen werden kann, um CRUD-Operationen (CRUD = Common Database) auszuführen, um das erneute Schreiben des ADO.NET-Codes in mehrere Lösungen zu ersparen. Um dies zu flexibilisieren, gibt es eine Reihe von Konstruktorüberladungen auf der Grundlage der verschiedenen Datenbankauthentifizierungstypen und Instanztypen usw. Die Klasse ist wie folgt:C# reflection - Auswahl der Konstruktorüberladung basierend auf verfügbaren Parametern

class Database 
{ 
    // default instance with Windows authentication 
    // constructor 1 
    public Database(string server, string database, bool persistSecurityInfo) 
    { 
     _server = server; 
     _database = database; 
     _persistSecurityInfo = persistSecurityInfo; 
     _integratedSecurity = "True"; 
     _connectionString = "Data Source=" + server + ";Initial Catalog=" + database + ";Persist Security Info=" + persistSecurityInfo.ToString() + ";Integrated Security=True"; 
    } 

    // named instance using Windows authentication 
    // constructor 2 
    public Database(string server, string instance, string database, bool persistSecurityInfo) : this(server, database, persistSecurityInfo) 
    { 
     _instance = instance; 
     _integratedSecurity = "True"; 
     _connectionString = "Data Source=" + server + "\\" + instance + ";Initial Catalog=" + database + ";Persist Security Info=" + persistSecurityInfo.ToString() + ";Integrated Security=True"; 
    } 

    // default instance with SQL authentication 
    // constructor 3 
    public Database(string server, string database, bool persistSecurityInfo, string userName, string password) : this(server, database, persistSecurityInfo) 
    { 
     _userName = userName; 
     _password = password; 
     _integratedSecurity = "False"; 
     _connectionString = "Data Source=" + server + ";Initial Catalog=" + database + ";Persist Security Info=" + persistSecurityInfo.ToString() + ";User ID=" + userName + ";Password=" + password; 
    } 

    // named instance with SQL authentication 
    // constructor 4 
    public Database(string server, string instance, string database, bool persistSecurityInfo, string userName, string password) : this(server, database, persistSecurityInfo, userName, password) 
    { 
     _instance = instance; 
     _integratedSecurity = "False"; 
     _connectionString = "Data Source=" + server + "\\" + instance + ";Initial Catalog=" + database + ";Persist Security Info=" + persistSecurityInfo.ToString() + ";User ID=" + userName + ";Password=" + password; 
    } 

    private string _server; 
    private string _instance; 
    private string _database; 
    private bool _persistSecurityInfo; 
    private string _userName; 
    private string _password; 
    private string _integratedSecurity; 

    private string _connectionString; 
    private string _query; 

    //CRUD Methods here 
} 

Ich habe eine Konsolenanwendung geschrieben, die auf eine Datenbank schreibt. Wenn die Anwendung ausgeführt wird, stellt der Benutzer einige Befehlszeilenschalter zur Verfügung.

Einige der Schalter sind wie folgt (Es gibt andere, die sich auf die Bedienung des Programms, die ich hier nicht enthalten):

  • /s: Datenbankservername
  • /i: Datenbank Name
  • /d: Datenbankname
  • /n: integrierte Sicherheit (Wahr oder Falsch)
  • /u: Benutzername db
  • /p: db Passwort

/i,/u und/p sind optional (zB wenn ein Instanzname nicht angegeben wird, nimmt das Programm es ist, zu einer Standardinstanz auf/s verbinden)

Daher ich brauche das Programm, um zur Laufzeit zu entscheiden, welcher Konstruktor basierend auf welchen Argumenten aufgerufen werden soll.

Pseudo-Beispiel hier

Class Program 
{ 
    static void Main(string[] args) 
    { 
     foreach (string arg in args[]) 
     { 
      //code to work out which parameters have been provided here and adds them to array. Also other code which checks integrity such as ensuring there is no username without a password and vice versa etc. 
      string[] suppliedParameters; 

      //if there is a /i , /u , /p parameters, use constructor 4 
      //if there is a /u and /p but no /i, use constructor 3 
      //if there is an /i but no /u or /n use constructor 2 
      //if there is no /i, /u or /n, use constructor 1 
     } 
    } 
} 

Ich weiß, ich Reflektion verwenden, um den entsprechenden Konstruktor auszuführen, und dass ich die Auswahl des Konstruktor eine switch-Anweisung in der Methode Main erreichen könnte, die die Tests in der Logik führt oben, aber ich frage mich nur, ob es eine vielleicht elegantere Möglichkeit gibt, dies zu tun?

+2

Es ist leichter für Sie, nur einen Standardkonstruktor zu verwenden und dann Klasseneigenschaften zu verwenden, um die eingegebenen Werte einzuschalten. – Felype

Antwort

1

Wenn Sie möchten, dann Reflexion verwenden, Activator.CreateInstance Methode verwenden, die als Parameter Typ und Array von Objekten akzeptiert. Je nach Anzahl der Elemente in Array- und Elementtypen wird der erforderliche Konstruktor automatisch aufgerufen.

+0

Sieht so aus, als ob ich es wollte, ich gebe es eine Chance – SEarle1986

+0

Als Antwort markieren, wenn Ihre Antwort gefunden wurde – CreativeManix

+0

Ich musste als Typ-Datenbank wie folgt DataBase db = (Database) Activator.CreateInstance (typeof (Datenbank), Argumente); aber anders als das, yep es funktioniert - Danke! – SEarle1986

1

Ich schlage einen einfacheren Ansatz vor. Verwenden Sie einen einzigen Konstruktor, der Ihre Mitglieder appriately setzt:

public MyClass(params string[] switches) 
{ 
    if(switches.Contains("/i") this.i = ... 
    ... 
} 

Sie können auch eine einfache Liste erstellen mit allen Optionen, deren Schalter true.

dieser Konstruktor einfach aufrufen verwenden:

var instance = Activator.CreateInstance(myType, suppliedParameters); 
Verwandte Themen