Frage

Das Projekt an dem ich arbeite erfordert einige Ausführungen zu einem bestimmten Zeitpunkt durchgeführt werden. Ich bin nicht sicher, was der beste Weg, um mit dieser Situation umgehen würde. Die Methode muss fähig sein Server-Neustart / Wartung, um zu überleben. Und Methodenaufrufe müssen programmatisch sein.

Ich erwäge gehen diesen Weg:

Ich habe eine Tabelle in der Datenbank haben könnte (oder sogar eine Nachrichtenwarteschlange) genannt TaskTable die TaskId (PK), Taskname (varchar), Taskstatus (Enum Erfolg, scheiterte, geplant) und TimeOfExecution haben könnte. Aber ich brauche einen Windows-Dienst, den die Datenbank für alle nicht ausgeführten Aufgaben in regelmäßigen Abständen Umfragen. Problem Ich bin vor ist, dass: Was ich als der Taskname in der Datenbank speichern? Klassenname? Klassen- und Methodennamen ToString? Und wie kann ich die Zeichenfolge zurück konvertieren und programmatisch die Methodenaufrufe aufrufe (Ich will nicht eine riesige switch-Anweisung haben)? Eine typtical Aufgabe würde wie folgt aussehen. So ned ich den Namen der Aufgabe „SendIncompleteNotification“ erhalten zu können und Klassennamen speichern sie in der Datenbank und auf retrival invoke programmatisch

public static Task<string> SendIncompleteNotification
{
  get
    {
      return new Task<string>
        (
          a => Console.WriteLine("Sample Task")
          , "This is a sample task which does nothing."
        );
   }
}

Das Problem ist jetzt, ich Problem habe progrmatically die Methode / Eigenschaftsnamen zu speichern.

var type = ApplicationTask.SendIncompleteNotification.GetType();
//type.Name shows "Task`1" rather than SendIncompleteNotification

Gibt es bessere Möglichkeiten, um mit dieser Situation umzugehen? Dank!

Aktualisiert: Leider war mein Kopf dreht. Ich erkannte nun, was ich falsch gemacht habe war eine andere Methode / Eigenschaft zu haben, um meine Aufgabe zurückzukehren. Was hätte ich getan war eine neue Klasse inhrite von meiner Aufgabe zu haben. Und da kann ich einfach die Klassennamen bekommen und die Zeichenfolge in db speichern und später retireve zurück und aufrufen.

War es hilfreich?

Lösung

Ist die Datenbank eine Anforderung?

Wenn nicht, was über einen Windows Scheduled Task (sie haben eine Tendenz zu „einfach funktionieren“), die in eine allgemeine Konsolenanwendung aufruft. Die Argumente für die Konsole app könnten sein:

  • Eine DLL die Aufgabe enthält, ausführen
  • Der Name einer Klasse Implementierung einer Schnittstelle, die Sie definieren
  • Andere Argumente

So können Sie alle Ihre Aufgaben in eine Baugruppe setzen können, oder mehr. Alternativ können Sie ein Attribut erstellen, anwenden dieses Attribut auf Ihre Aufgaben ihnen einen „freundlichen Namen“ zu geben, und verwenden Reflexion über die Anordnung Klassen mit dem passenden Attribute zu finden.

Edit: Beispiel:

interface ITask
{
    void Execute(ExcecutionContext context);
}

[TaskName("Send Emails")
class SendEmailsTask : ITask
{
    public void Execute(ExcecutionContext context) 
    {
        // Send emails. ExecutionContext might contain a dictionary of 
        // key/value pairs for additional arguments needed for your task. 
    }
}

class TaskExecuter 
{
    public void ExecuteTask(string name) 
    {
        // "name" comes from the database entry
        var types = Assembly.GetExecutingAssembly().GetTypes();    
        foreach (var type in types)
        {
            // Check type.GetCustomAttributes for the TaskAttribute, then check the name
        }
    }
}

Edit 2: Dies ist in Antwort auf Ihr Codebeispiel

.
class YourClass
{
    public static Task<string> SendIncompleteNotification
    {
        get {
            return new Task<string>(
                s => Console.WriteLine("Executing task... arguments: {0}", s),
                "My task");
        }
    }
}


interface ITask
{
    void Execute(object o);
}

class Task<T> : ITask
{        
    public Task(Action<T> action, string name)
    {
        Action = action;
    }

    public string Name { get; set; }
    public Action<T> Action { get; set; }

    void ITask.Execute(object o)
    {
        Action((T)o);
    }
}

class Program
{
    static void Main(string[] args)
    {
        // Assume that this is what is stored in the database
        var typeName = typeof (YourClass).FullName;
        var propertyName = "SendIncompleteNotification";
        var arguments = "some arguments";

        // Execute the task
        var type = Type.GetType(typeName);
        var property = type.GetProperty(propertyName);
        var task = (ITask)property.GetValue(null, null);
        task.Execute(arguments);
        Console.ReadKey();
    }
}

Andere Tipps

Sie können in Windows Workflow aussehen soll. Sie sind für lange laufende Prozesse entwickelt, kann auf eine Datenbank und aufgeweckt auf Ereignis oder Timer beibehalten werden, soweit ich weiß.

Speichern Sie die Baugruppe Fullname, und geben Sie Fullname und den Methodennamen. Unter der Annahme, die Methodensignatur ist etwas vorhersehbar (wie keine Parameter und Rückkehr void)

1) Erstellen einer Instanz der Anordnung der statischen Methode Loadfrom des Assembly-Typ.

2) erhält einen Verweis auf den Klassentyp aus der Assembly der GetType-Methode mit

3) erhalten Method Instanz vom Typ der GetMethod Methode mit

4) eine Instanz des Typs erstellen mit Activator.CreateInstance

5) führt die Methode Invoke der Method Instanz mit, in der Klasseninstanz von Schritt vorbei 4. (sorry, dass ich an einem öffentlichen Computer bin ohne eine Kopie von VS echten Code heraus anzukurbeln, aber diese fünf Schritten würde tun.

Auch wenn Sie mit SQL 2005 betrachten ein SqlDependency-Objekt und anstatt Polling „benachrichtigt“, wenn Ihre talbe Änderungen zu werden.

Haben Sie sich unter Quartz , es funktioniert ziemlich gut, und ich bin mir ziemlich sicher, dass es implementiert alle Funktionen, die Sie benötigen.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top