Pregunta

El proyecto que estoy trabajando en algunas ejecuciones requiere para ser hecho en un momento determinado. No estoy seguro de lo que sería la mejor manera de hacer frente a esta situación. El método debe ser capaz de sobrevivir a reiniciar el servidor / mantenimiento. Y las llamadas a métodos deben ser mediante programación.

Estoy pensando en ir por este camino:

Podría tener una tabla en la base de datos (o incluso una cola de mensajes) denominada TaskTable que podría tener TaskID (PK), TaskName (varchar), TaskStatus (éxito enumeración, fracasado, programado) y TimeOfExecution. Pero necesito un servicio de Windows que comprueba periódicamente la base de datos para las tareas no ejecutadas. El problema que estoy enfrentando es que: ¿Qué puedo usar como el TaskName para guardar en la base de datos? ¿Nombre de la clase? clase y nombre del método ToString? ¿Y cómo puedo convertir la cadena hacia atrás y programación invocar las llamadas de método (que no quieren tener una sentencia switch gigante)? Una tarea typtical se vería más adelante. Así que NED para poder obtener el nombre de la tarea "SendIncompleteNotification" y nombre de la clase guardarlo en la base de datos y en la invocación de retrival programáticamente

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

El problema ahora es que estoy teniendo problema al guardar el nombre del método / propiedad progrmatically.

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

¿Hay algún mejores maneras de hacer frente a esta situación? Gracias!

Actualizado: Lo siento mi cabeza daba vueltas. Ahora me di cuenta de lo que hice mal era tener otro método / propiedad para devolver mi tarea. Lo que debería haber hecho era tener una nueva clase inhrite de mi tarea. Y no puedo conseguir fácilmente el nombre de clase y guardar la cadena en db y luego volver retireve e invocar.

¿Fue útil?

Solución

Es la base de datos un requisito?

Si no, ¿qué acerca de una tarea programada de Windows (tienen una tendencia a "sólo trabajo") que pone en una aplicación general de la consola. Los argumentos para la aplicación de la consola podrían ser:

  • Una DLL que contiene la tarea a ejecutar
  • El nombre de una clase que implementa una interfaz que defina
  • Otros argumentos

De esta manera usted puede poner todas sus tareas en una asamblea, o múltiple. Como alternativa, puede crear un atributo, aplicar ese atributo a sus tareas para darles un "nombre", y utilizar la reflexión sobre el conjunto para encontrar clases con el atributo de adaptación.

Edit: ejemplo:

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
        }
    }
}

Edición 2: Esto es en respuesta a su ejemplo de código

.
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();
    }
}

Otros consejos

Es posible que desee ver en Windows Workflow. Están diseñados para procesos de larga ejecución, se pueden conservar a una base de datos y despertado el evento o tiempo, por lo que yo sé.

Almacenar el NombreCompleto montaje, y escriba NombreCompleto y el nombre del método. Suponiendo que la firma del método es algo predecible (como no hay parámetros de pleno derecho de regresar)

1) crear una instancia del conjunto utilizando el método LoadFrom estática del tipo Asamblea.

2) obtener una referencia al tipo de clase de su montaje utilizando el método GetType

3) obtener ejemplo MethodInfo del tipo usando el método GetMethod

4) crear una instancia del tipo que utiliza Activator.CreateInstance

5) ejecutar el método que utiliza la invocación de la instancia MethodInfo, pasando en la instancia de clase desde el paso 4. (lo siento que estoy en un equipo público sin una copia de VS de poner hacia fuera código real, pero esos 5 pasos serían hacer.

Además, si usted está utilizando SQL 2005 considere el uso de un objeto SqlDependency y conseguir "notificado" cuando sus talbe cambios en lugar de votación.

¿Has mirado en cuarzo , funciona bastante bien, y estoy bastante seguro de que implementa toda las características que necesita.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top