2011-03-04 11 views
5

Mi jefe me ha pedido que investigue un motor de cálculo. Efectivamente, el usuario tendrá una tabla de datos en la que se pueden realizar cálculos. También podrán construir sus propios cálculos basados ​​en ciertas restricciones que aplicamos (los cálculos generados se almacenarán en la base de datos)Llamando a los métodos de C# dinámicamente en base a los datos de la base de datos

¿Es posible llamar a un método específico en C#, dependiendo de lo que se almacena en el ¿base de datos? Entonces, si la base de datos dice, un cálculo debería realizar una desviación estándar. Cuando obtenemos esa información de la base de datos, ¿es posible llamar a un método de desviación estándar que tendremos en C#?

Espero que esto esté claro.

+0

use Reflection, hay muchos ejemplos – Stecya

+0

puede codificar cada método como un entero y almacenarlo en la base de datos y luego realizar un cambio en ese entero, teniendo una llamada al método correspondiente en cada caso? –

+2

¿Puede explicarlo más claramente porque por lo que ha escrito le sugiero que simplemente se conecte a DB desde su aplicación C# y luego establezca algunas condiciones con respecto a qué método se debe llamar en qué situación y eso es todo. ¿O tal vez quieres algo más? – Tobiasz

Respuesta

3

Teniendo en cuenta la cantidad pequeña/conocida de las operaciones que se ejecutan en sus datos, optaría a codificar manualmente estas operaciones, basado en los datos recuperados de la base de datos . Para extensibilidad/mantenibilidad, es mejor crear un diseño adecuado para esto en lugar de usar una simple declaración de cambio. Supongo que el Strategy pattern se ajustará a tus necesidades.

Como han indicado otros, puede usar reflection, para llamar a los métodos especificados en la base de datos. El problema con este enfoque es que los datos en su base de datos están fuertemente vinculados a las firmas de métodos. Esto es menos sostenible que el primer enfoque, pero permite una gran extensibilidad con ajustes de código mínimos. Otro inconveniente es usar MethodInfo.Invoke() es bastante lento.

Si opta por la reflexión, pero encuentra que el enfoque Invoke() es demasiado lento, puedo recomendar this article by Jon Skeet que explica cómo convertir un MethodInfo en una instancia de delegado. Esto proporciona un aumento de velocidad importante. Escribí a generic implementation using expression trees para esto recientemente.

En general, parece que la opción 1 sigue siendo la mejor para sus propósitos.

0

Puede usar la instrucción switch en C# para ejecutar la operación que desee dependiendo del valor del campo (o escalar) de su registro proveniente de la base de datos. Esto está bien si tiene un número pequeño/limitado de operaciones compatibles, de lo contrario, por supuesto, podría usar reflection y la clase MethodInfo para invocar un método miembro por "nombre de cadena" en una determinada clase.

+0

Creo que la enumeración (primera opción) es mucho más rápida y segura. ¿Qué evitaría que alguien coloque File.Delete() u otros nombres desagradables en el DB? – jonathanpeppers

+0

Acepto, no estaba pensando en la compilación de código de tiempo de ejecución como segundo punto, sino como teniendo el nombre del método de CalculationEngine en el archivo db. –

2

Sí, esto es posible; se llama reflejo y es una característica estándar de C#. Muchos tutoriales existen en la web; aquí hay algo bastante simple código de ejemplo:

using System; 
using System.Reflection; 

class CallMethodByName 
{ 
    string name; 

    CallMethodByName (string name) 
    { 
     this.name = name; 
    } 

    public void DisplayName()  // method to call by name 
    { 
     Console.WriteLine (name); // prove we called it 
    } 

    static void Main() 
    { 
     // Instantiate this class 
     CallMethodByName cmbn = new CallMethodByName ("CSO"); 

     // Get the desired method by name: DisplayName 
     MethodInfo methodInfo = 
     typeof (CallMethodByName).GetMethod ("DisplayName"); 

     // Use the instance to call the method without arguments 
     methodInfo.Invoke (cmbn, null); 
    } 
} 

http://en.csharp-online.net/CSharp_FAQ:_How_call_a_method_using_a_name_string

0

Sí, puede hacerlo utilizando la reflexión. Podría escribir una clase que contenga todas las operaciones que el usuario podría hacer y luego llamar a sus métodos dinámicamente.

public static class UserOperations 
{ 
    public static decimal Average(IEnumerable<decimal> source) 
    { 
     return source.Average(); 
    } 

    // Other methods 
} 


class Program 
{ 
    static void Main(string[] args) 
    { 
     // The operation retrieved from the db 
     string operation = "Average"; 
     // The items on which the operations should be performed 
     decimal[] items = { 22m, 55m, 77m }; 

     object result = typeof(UserOperations).GetMethod(operation).Invoke(null, new object[] { items }); 
     Console.WriteLine(result); 
     Console.ReadLine(); 
    } 
} 
Cuestiones relacionadas