Динамический вызов методов C # на основе данных из базы данных - PullRequest
5 голосов
/ 04 марта 2011

Мой босс попросил меня изучить механизм расчета. По сути, у пользователя будет таблица данных, по которой можно выполнять расчеты. Они также смогут строить свои собственные расчеты на основе определенных нами ограничений (построенные расчеты будут затем сохраняться в базе данных)

Можно ли вызвать конкретный метод в C #, в зависимости от того, что хранится в базе данных? Так что, если база данных говорит, расчет должен выполнить стандартное отклонение. Когда мы получим эту информацию из базы данных, можно ли будет вызвать метод стандартного отклонения, который будет у нас в C #?

Надеюсь, это понятно.

Ответы [ 6 ]

3 голосов
/ 04 марта 2011

Учитывая малое / известное количество операций, которые будут выполняться над вашими данными, я бы решил вручную кодировать эти операции на основе данных, полученных из базы данных.Для расширяемости / ремонтопригодности лучше создать для этого надлежащий дизайн, а не использовать простой оператор switch.Я предполагаю, что шаблон стратегии подойдет вашим потребностям.

Как уже говорили другие, вы могли бы использовать отражение , чтобы вызывать методы какуказано в базе данных.Проблема этого подхода заключается в том, что данные в вашей базе данных тесно связаны с сигнатурами методов.Это менее приемлемо, чем первый подход, но допускает большую расширяемость с минимальными корректировками кода.Еще одним недостатком является то, что MethodInfo.Invoke() довольно медленный.

Если вы выбрали бы рефлексию, но нашли, что подход Invoke() слишком медленный, я могу порекомендовать эту статью Джона Скита который объясняет, как преобразовать MethodInfo в экземпляр делегата.Это дает значительный прирост скорости.Недавно я написал обобщенную реализацию, использующую деревья выражений .

В общем, кажется, что вариант 1 по-прежнему лучше всего подходит для ваших целей.

2 голосов
/ 04 марта 2011

Да, это возможно;он называется отражение и это стандартная функция C #.Многие учебные пособия существуют в Интернете;вот несколько довольно простых примеров кода:

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 голосов
/ 04 марта 2011

Да, вы можете сделать это с помощью Reflection.Вы могли бы написать класс, содержащий все операции, которые мог бы выполнить пользователь, а затем динамически вызывать его методы.

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();
    }
}
0 голосов
/ 04 марта 2011

Я бы посоветовал вам реализовать шаблон стратегии (http://www.dofactory.com/Patterns/PatternStrategy.aspx)

. Вы можете загружать разные стратегии (алгоритмы) для различных необходимых вычислений.

Также есть хороший пост http://blogs.microsoft.co.il/blogs/gilf/archive/2009/11/22/applying-strategy-pattern-instead-of-using-switch-statements.aspx

0 голосов
/ 04 марта 2011

Вы можете хранить операции в БД и использовать Microsoft.CSharp.CSharpCodeProvider для компиляции кода на лету.

Смотрите пример здесь: Выполните код во время выполнения

0 голосов
/ 04 марта 2011

Вы можете использовать оператор switch в C # для выполнения требуемой операции в зависимости от значения поля вашей записи (или скаляра), поступающего из базы данных.Это нормально, если у вас есть небольшое / ограниченное число поддерживаемых операций, в противном случае, конечно, вы можете использовать отражение и класс MethodInfo для вызова метода-члена с помощью «строкового имени» в определенном классе.

...