RError.com

RError.com Logo RError.com Logo

RError.com Navigation

  • 主页

Mobile menu

Close
  • 主页
  • 系统&网络
    • 热门问题
    • 最新问题
    • 标签
  • Ubuntu
    • 热门问题
    • 最新问题
    • 标签
  • 帮助
主页 / 问题 / 761471
Accepted
Fresto
Fresto
Asked:2020-12-21 20:45:14 +0000 UTC2020-12-21 20:45:14 +0000 UTC 2020-12-21 20:45:14 +0000 UTC

根据 ComboBox 的值调用方法

  • 772

代码中有很多计算,根据初始数据,我得到不同的结果。初始数据由 value 确定ComboBox,因此,根据此,将外部库方法之一分配给变量。实现这一点的最佳方法是什么?因此,我认为,取决于Combobox将变量与库中方法的名称等同起来string并使用reflection. 而在代码中,我需要改变的只是通过开关迭代值Combobox并分配方法的名称。因为ComboBox最终会有 30-40 个值。我们需要一些通用和简洁的东西。

c#
  • 2 2 个回答
  • 10 Views

2 个回答

  • Voted
  1. VladD
    2020-12-21T21:29:54Z2020-12-21T21:29:54Z

    我会做一个这样的数据结构:

    public class MethodDescription
    {
        public string Name { get; }
        public Action Method { get; }
    
        public MethodDescription(string name, Action method)
        {
            Name = name;
            Method = method;
        }
    }
    

    现在外部程序集在您手中,它可以轻松地提供您需要的所有方法的列表。例如,像这样:

    public static class Methods
    {
        public static IEnumerable<MethodDescription> All { get; } =
            new[]
            {
                new MethodDescription("First", MyClass.First),
                new MethodDescription("Second", MyClass.Second),
                new MethodDescription("Very big", MyClass.VeryBig),
                new MethodDescription("Not at all", MyClass.NotAtAll)
                // добавляйте сюда ещё
            };
    }
    

    等等。您也可以不手动收集方法,而是通过反射。

    在客户端,一切都很简单:

    <ComboBox ItemsSource="{Binding Source={x:Static extAssembly:Methods.All}}"
              DisplayMemberName="Name"/>
    
    • 3
  2. Best Answer
    Андрей NOP
    2020-12-21T21:34:07Z2020-12-21T21:34:07Z

    获取接口:

    public interface IOperation
    {
        int Execute(int p1, int p2);
    }
    

    代替静态方法,创建实现它的类:

    public class AddOperation : IOperation
    {
        public int Execute(int p1, int p2)
        {
            return p1 + p2;
        }
    }
    
    public class MulOperation : IOperation
    {
        public int Execute(int p1, int p2)
        {
            return p1 * p2;
        }
    }
    

    然后,您可以获得实现给定接口的类列表,如下所示:

    var operationTypes =
        typeof(Program)
            .Assembly.GetTypes()
            .Where(t => t.GetInterfaces().Contains(typeof(IOperation)))
            .ToList();
    

    然后,在选择所需的操作后,我们创建它的一个实例并运行它:

    var operation = (IOperation)Activator.CreateInstance(operationTypes[0]);
    Console.WriteLine(operation.Execute(1, 2));
    

    这种方法的缺点(对我来说 - 无关紧要)是这些具有操作的类必须有一个没有参数的构造函数。


    另一种方法是通过反射来获取一个类/程序集的所有方法,为了将必要的方法与其他方法区分开来,可以创建一个自定义属性:

    [AttributeUsage(AttributeTargets.Method)]
    public class ExecuteAttribute : Attribute { }
    

    我们用属性标记必要的方法:

    public static class Library
    {
        [Execute]
        public static int SumOperation(int p1, int p2)
        {
            return p1 + p2;
        }
    
        [Execute]
        public static int MulOperation(int p1, int p2)
        {
            return p1 * p2;
        }
    }
    

    我们得到列表:

    var methods = 
        typeof(Library)
            .GetMethods()
            .Where(m => m.GetCustomAttribute<ExecuteAttribute>() != null)
            .ToList();
    

    我们称之为必需的:

    Console.WriteLine((int)methods[0].Invoke(null, new object[] { 1, 2 }));
    

    这种方法的缺点是没有针对方法可能具有不同签名的事实的保护,这将导致执行期间的错误。

    如果需要,您可以在属性中创建一个属性来指示方法的名称:

    [AttributeUsage(AttributeTargets.Method)]
    public class ExecuteAttribute : Attribute
    {
        public string Name { get; }
        public ExecuteAttribute(string name)
        {
            Name = name;
        }
    }
    

    然后,您可以获得这样的名称:

    var method = methods[0];
    string name = method.GetCustomAttribute<ExecuteAttribute>().Name;
    

    并问:[Execute("Сложить")]

    好吧,为了方便调用方法,您可以基于它创建一个委托(感谢@VladD 的提示):

    var operation = (Func<int, int, int>)Delegate.CreateDelegate(typeof(Func<int, int, int>), method);
    Console.WriteLine($"{name} 1 и 2 будет {operation(1, 2)}");
    
    • 2

相关问题

Sidebar

Stats

  • 问题 10021
  • Answers 30001
  • 最佳答案 8000
  • 用户 6900
  • 常问
  • 回答
  • Marko Smith

    Python 3.6 - 安装 MySQL (Windows)

    • 1 个回答
  • Marko Smith

    C++ 编写程序“计算单个岛屿”。填充一个二维数组 12x12 0 和 1

    • 2 个回答
  • Marko Smith

    返回指针的函数

    • 1 个回答
  • Marko Smith

    我使用 django 管理面板添加图像,但它没有显示

    • 1 个回答
  • Marko Smith

    这些条目是什么意思,它们的完整等效项是什么样的

    • 2 个回答
  • Marko Smith

    浏览器仍然缓存文件数据

    • 1 个回答
  • Marko Smith

    在 Excel VBA 中激活工作表的问题

    • 3 个回答
  • Marko Smith

    为什么内置类型中包含复数而小数不包含?

    • 2 个回答
  • Marko Smith

    获得唯一途径

    • 3 个回答
  • Marko Smith

    告诉我一个像幻灯片一样创建滚动的库

    • 1 个回答
  • Martin Hope
    Air 究竟是什么标识了网站访问者? 2020-11-03 15:49:20 +0000 UTC
  • Martin Hope
    Алексей Шиманский 如何以及通过什么方式来查找 Javascript 代码中的错误? 2020-08-03 00:21:37 +0000 UTC
  • Martin Hope
    Qwertiy 号码显示 9223372036854775807 2020-07-11 18:16:49 +0000 UTC
  • Martin Hope
    user216109 如何为黑客设下陷阱,或充分击退攻击? 2020-05-10 02:22:52 +0000 UTC
  • Martin Hope
    Qwertiy 并变成3个无穷大 2020-11-06 07:15:57 +0000 UTC
  • Martin Hope
    koks_rs 什么是样板代码? 2020-10-27 15:43:19 +0000 UTC
  • Martin Hope
    user207618 Codegolf——组合选择算法的实现 2020-10-23 18:46:29 +0000 UTC
  • Martin Hope
    Sirop4ik 向 git 提交发布的正确方法是什么? 2020-10-05 00:02:00 +0000 UTC
  • Martin Hope
    faoxis 为什么在这么多示例中函数都称为 foo? 2020-08-15 04:42:49 +0000 UTC
  • Martin Hope
    Pavel Mayorov 如何从事件或回调函数中返回值?或者至少等他们完成。 2020-08-11 16:49:28 +0000 UTC

热门标签

javascript python java php c# c++ html android jquery mysql

Explore

  • 主页
  • 问题
    • 热门问题
    • 最新问题
  • 标签
  • 帮助

Footer

RError.com

关于我们

  • 关于我们
  • 联系我们

Legal Stuff

  • Privacy Policy

帮助

© 2023 RError.com All Rights Reserve   沪ICP备12040472号-5