2013-08-29 1 views
0

Мне нужно дать возможность добавить любой метод, возвращающий double, и внося любое количество двойных параметров в словарь. Помоги мне, пожалуйста.Как я могу дать пользователю возможность добавлять методы любого типа в словарь <string, Delegate>?

class Program 
{ 
Dictionary<string, Delegate> _functions; 
static double MyFunc (double x, double y, double z, double q, double r, double t) 
    { 
     return 100; 
    } 
// and the user can create his functions with any amount of parameters 
static void AddFunction (Delegate d) 
    {    
     _functions.Add (d.Method.Name, d); 
    } 
static void Main (string [] args) 
    { 
     _functions = new Dictionary<string, Delegate>(); 
     Program.AddFunction(MyFunc); 
    } 
} 

ответ

1

Ну, я не уверен, как вы планируете точно называть это. Так как у вас есть переменная количество входов, вы можете рассматривать их как вход массива.

delegate double MyDictionaryDelegate(params double[] input); 

static Dictionary<string, MyDictionaryDelegate> _functions; 

static void AddFunction (MyDictionaryDelegate d) 
{    
    _functions.Add(d.Method.Name, d); 
} 

Но это по существу превращает названные функции в коллекции обработки (с любым из выгод/ограничений это подразумевает):

public static double MyFunc (params double[] input) 
{ 
    return input.Sum(); 
} 

Так что ваше использование может быть как:

_functions = new Dictionary<string, MyDictionaryDelegate>(); 
AddFunction(MyFunc); 
Console.WriteLine(_functions["MyFunc"](1, 2.5, 0));//3.5 

Но я подозреваю, что лучше сохранить исходный список параметров, а не список, например:

public static double AnotherFunc(double x, double y, double z) 
{ 
    return x + y + z; 
} 

Вам может просто иметь функцию обертку:

public static double AnotherFunc(params double[] input) 
{ 
    //preferably with some check that the proper number of 
    //input parameters are included 
    return AnotherFuncImpl(input[0], input[1], input[2]); 
} 

Но это, кажется, общий вид опасен для меня; Я не уверен, что рекомендую.

EDIT: Вот еще один вариант, чтобы избежать массивов param double[] input и всегда иметь фиксированные аргументы параметров. Используйте Delegate, как и у вас, но вам нужно будет использовать его DynamicInvoke. Кроме того, вы бы объявить несколько AddFunction перегрузки для каждого числа параметров, которые вы ожидаете достаточно иметь:

static Dictionary<string, Delegate> _functions; 

private static void AddFunction (string functionName, Delegate d) 
{    
    _functions.Add(functionName, d); 
} 

private static void AddFunction(Func<double> d) 
{    
    _functions.Add(d.Method.Name, d); 
} 

private static void AddFunction(Func<double, double> d) 
{    
    _functions.Add(d.Method.Name, d); 
} 

private static void AddFunction(Func<double, double, double> d) 
{    
    _functions.Add(d.Method.Name, d); 
} 

private static void AddFunction(Func<double, double, double, double> d) 
{    
    _functions.Add(d.Method.Name, d); 
} 

//additional overloads up to N parameters 

Тогда может быть использование:

public static double MyFunc(double x, double y, double z) 
{ 
    return x + y + z; 
} 

_functions = new Dictionary<string, Delegate>(); 
AddFunction(MyFunc); 
Console.WriteLine(_functions["MyFunc"].DynamicInvoke(1, 2.5, 0));//3.5 

Но опять же, это может потерпеть неудачу, если вызывающему неправильно набрал DynamicInvoke с точным номером необходимых параметров (не более, не менее).

Я по-прежнему чувствую себя как будто в целом, независимо от того, что вы делаете, это принесет пользу из другого дизайна.

+0

На самом деле проблема заключается в следующем: мне нужно написать консольный калькулятор. Одна из перегрузок метода AddFunction выглядит так: – Dima

+0

@ Dima: Я предполагаю, что к вашему комментарию придет больше? :) –

+0

Спасибо за первый ответ. Затем я хотел бы ответить на следующее: давайте представим ситуацию, когда функция принимает параметр double [], но пользователь не должен создавать какие-либо массивы. Вместо этого мы будем иметь в консоли: «MyFunk (10,20,30,40 и т. Д.) =« В моем словаре у меня есть делегат с методом 1-param (массив), но мне нужно знать, сколько параметров используемый в консоли для создания соответствующего массива и передачи его делегату в словаре. Мне действительно нужно получить эту информацию от разбора строки, или есть более умный способ сделать это? – Dima

0

Определить новый объект класса, который имеет делегат и список параметров вам требуется, то dictionary<string, clsObject> будет, как вы определяете словарь.

0

В ролях метод как Func<T1, T2, .., TResult> при добавлении его к коллекции:

Program.AddFunction(
    (Func<double, double, double, double, double, double, double>)MyFunc); 
0

ли вы имеете в виду defining a delegate with the params modifier on its arguments? Ответ, по-видимому, нет, потому что компилятор преобразует дополнительные аргументы в массив в вызове метода, но не для делегатов. См. Ссылку для некоторых решений.

0

Вам нужно объявить делегата как возвращающего двойное число, и, взяв парам удвоений, вот полный рабочий пример.

public class Widget 
{ 
    // declares a delegate called AddDelegate that takes a param of doubles 
    public delegate double AddDelegate(params double[] dbls); 
    Dictionary<string, AddDelegate> functions; 

    public Widget() 
    { 
     functions = new Dictionary<string, AddDelegate>(); 
    } 

    public void Add(AddDelegate d) 
    { 
     functions.Add(d.Method.Name, d); 
    } 

    public void Run() 
    { 
     foreach (var kvp in functions) 
     { 
      // write out the name and result of each function added to our list 
      Console.Write(kvp.Key); 
      Console.Write(": "); 
      Console.Write(kvp.Value(10.0, 10.0, 10.0, 10.0)); 
     } 
    } 
} 

class Program 
{ 
    static double CalcDouble(params double[] dbls) 
    { 
     double total = 0.0; 
     foreach (double d in dbls) 
     { 
      total += d; 
     } 
     return total; 
    } 


    static void Main(string[] args) 
    { 
     var w = new Widget(); 
     w.Add(new Widget.AddDelegate(CalcDouble)); 
     w.Run(); 
    } 
} 
+0

Но вы не можете добавить метод с подписями 'double CalcDouble (double x, double y)'; каждый метод, который нужно добавить в словарь, должен иметь 'params double []' как единственный параметр. –

+0

Да, это почти единственный способ сделать то, что вы хотите сделать, если только вам не захочется обернуть все возможные перегрузки, которые вы когда-либо хотели использовать. –

Смежные вопросы