C# 属性和方法
C# attributes and methods
大家好,
最近我遇到了 Discord.NET Api 并爱上了命令的处理方式。本质上,要添加一个在你写 !ping
时执行的新命令,你可以这样做:
[Command("ping")]
public async Task Ping()
{
//some logic here
}
而且我真的很喜欢在现有 API 中集成新命令的简单性。所以我想重现正在发生的事情。一开始我被元编程的引入搞得一头雾水,现在感觉舒服了一点,于是尝试下手,设计了一个只能赋值给方法的Attribute:
[AttributeUsage(AttributeTargets.Method)]
public class Command : Attribute
{
public string Name { get; set; }
public Command(string name)
{
Name = name;
}
public Command()
{
Name = string.Empty;
}
}
然后的基本想法是,当我的控制台收到命令时,我可以 运行 一个方法,该方法具有命令属性和在控制台中输入的名称。因此,当我在控制台中输入“ping”时,将执行以下方法。
[Command("ping")]
public void Ping()
{
//do sth
}
现在进入复杂的部分。我如何找到特别是 运行 那个方法?那就是我现在被困的地方。在 .Net 纪录片或这里的 Whosebug 上,我真的没有发现任何关于这个问题的有用信息。无论如何,这是我的尝试:
public void Handle(string command)
{
var methods = from t in Assembly.GetExecutingAssembly().GetTypes()
where t.GetCustomAttributes<Command>().Count() > 0
select t;
//run method where command.name = ping
}
其背后的想法是,遍历程序集中所有可用的方法,然后将它们放入某种列表中,然后执行具有传入内容的 command.name 的方法Handle 函数的参数。当我让它工作时,我当然会在 class 的构造函数中初始化方法列表,而不是每次在调用 Handle 时调用它,但是为了简单起见,我的问题独立于此,以让我的例子最少。现在的问题是,如何遍历程序集中的所有方法,并将具有 command 属性的方法保存到集合中,以及如何 运行 具有特定值的方法 command.Name 属性?
我对整个反射的东西有点陌生,所以如果我做了其他愚蠢的事情或者你有关于那个主题的一般提示,请告诉我!!
提前致谢!!
我已经编写了一个小型演示应用程序,应该可以帮助您完成您的逻辑。总的来说,当然,它仍然有改进的空间,但它是有效的:
using System;
using System.Linq;
using System.Reflection;
namespace DemoApp
{
class Program
{
static void Main(string[] args)
{
string command = Console.ReadLine().Trim();
LogicProvider provider = new LogicProvider();
MethodInfo method = provider.GetType().GetMethods().FirstOrDefault((item) => item.GetCustomAttribute<CommandAttribute>().Identifier == command);
method?.Invoke(provider, null);
}
}
public class LogicProvider
{
[Command("DemoCommand")]
public void MyMethod()
{
Console.WriteLine("Here");
}
}
public class CommandAttribute : Attribute
{
public CommandAttribute(string identifier)
{
this.Identifier = identifier;
}
public string Identifier { get; } = null;
}
}
如果在控制台中输入 DemoCommand,则会在 LogicProvider 中搜索匹配方法。如果匹配,则执行。
整个过程也适用于具有参数的方法。在 method?.Invoke() 的情况下,这可以被指定。
大家好,
最近我遇到了 Discord.NET Api 并爱上了命令的处理方式。本质上,要添加一个在你写 !ping
时执行的新命令,你可以这样做:
[Command("ping")]
public async Task Ping()
{
//some logic here
}
而且我真的很喜欢在现有 API 中集成新命令的简单性。所以我想重现正在发生的事情。一开始我被元编程的引入搞得一头雾水,现在感觉舒服了一点,于是尝试下手,设计了一个只能赋值给方法的Attribute:
[AttributeUsage(AttributeTargets.Method)]
public class Command : Attribute
{
public string Name { get; set; }
public Command(string name)
{
Name = name;
}
public Command()
{
Name = string.Empty;
}
}
然后的基本想法是,当我的控制台收到命令时,我可以 运行 一个方法,该方法具有命令属性和在控制台中输入的名称。因此,当我在控制台中输入“ping”时,将执行以下方法。
[Command("ping")]
public void Ping()
{
//do sth
}
现在进入复杂的部分。我如何找到特别是 运行 那个方法?那就是我现在被困的地方。在 .Net 纪录片或这里的 Whosebug 上,我真的没有发现任何关于这个问题的有用信息。无论如何,这是我的尝试:
public void Handle(string command)
{
var methods = from t in Assembly.GetExecutingAssembly().GetTypes()
where t.GetCustomAttributes<Command>().Count() > 0
select t;
//run method where command.name = ping
}
其背后的想法是,遍历程序集中所有可用的方法,然后将它们放入某种列表中,然后执行具有传入内容的 command.name 的方法Handle 函数的参数。当我让它工作时,我当然会在 class 的构造函数中初始化方法列表,而不是每次在调用 Handle 时调用它,但是为了简单起见,我的问题独立于此,以让我的例子最少。现在的问题是,如何遍历程序集中的所有方法,并将具有 command 属性的方法保存到集合中,以及如何 运行 具有特定值的方法 command.Name 属性? 我对整个反射的东西有点陌生,所以如果我做了其他愚蠢的事情或者你有关于那个主题的一般提示,请告诉我!! 提前致谢!!
我已经编写了一个小型演示应用程序,应该可以帮助您完成您的逻辑。总的来说,当然,它仍然有改进的空间,但它是有效的:
using System;
using System.Linq;
using System.Reflection;
namespace DemoApp
{
class Program
{
static void Main(string[] args)
{
string command = Console.ReadLine().Trim();
LogicProvider provider = new LogicProvider();
MethodInfo method = provider.GetType().GetMethods().FirstOrDefault((item) => item.GetCustomAttribute<CommandAttribute>().Identifier == command);
method?.Invoke(provider, null);
}
}
public class LogicProvider
{
[Command("DemoCommand")]
public void MyMethod()
{
Console.WriteLine("Here");
}
}
public class CommandAttribute : Attribute
{
public CommandAttribute(string identifier)
{
this.Identifier = identifier;
}
public string Identifier { get; } = null;
}
}
如果在控制台中输入 DemoCommand,则会在 LogicProvider 中搜索匹配方法。如果匹配,则执行。
整个过程也适用于具有参数的方法。在 method?.Invoke() 的情况下,这可以被指定。