使用反射来获取具有特定属性值的方法

时间:2017-06-05 18:26:43

标签: c# linq

我有这个代表:

 public delegate void PacketHandler(Client client, Packet packet);

我有这个属性:

[AttributeUsage(AttributeTargets.Method, AllowMultiple = true)]
public sealed class PacketHandlerAttribute : Attribute
{
    public ServerType Server { get; private set; }
    public int Code { get; private set; }

    public PacketHandlerAttribute(ServerType server, int code)
    {
        this.Server = server;
        this.Code = code;
    }
}

我想根据给定的IEnumerable<Tuple<PacketHandlerAttribute, PacketHandler>>值创建一个返回ServerType的方法。因此,如果我使用ServerType.Server调用此方法,则会返回包含Server1作为其属性的所有方法。

到目前为止我做到了这一点:

public static IEnumerable<Doublet<PacketHandlerAttribute, PacketHandler>> GetPacketHandlers(ServerType server)
    {
        foreach (Type type in Assembly.GetExecutingAssembly().GetTypes())
        {
            foreach (MethodInfo method in type.GetMethods())
            {
                PacketHandlerAttribute attribute = (PacketHandlerAttribute)method.GetCustomAttribute(typeof(PacketHandlerAttribute));

                if (attribute != null)
                {
                    if (attribute.Server == server)
                    {
                        yield return new Doublet<PacketHandlerAttribute, PacketHandler>(attribute, (PacketHandler)Delegate.CreateDelegate(typeof(PacketHandler), method));
                    }
                }
            }
        }
    }

我想问一下这是否是正确的方法,以及如何通过LINQ缩短这一点?

1 个答案:

答案 0 :(得分:2)

我觉得这是有帮助的。

 var methods = from type in assembly.GetTypes()
                      from method in type.GetMethods()
                      let attribute = method.GetCustomAttributes(typeof(PacketHandlerAttribute), false).Cast<PacketHandlerAttribute>().FirstOrDefault()
                      where attribute?.Code == 1
                      select new { method, attribute };

你的方法

public IEnumerable<(PacketHandlerAttribute attribute, PacketHandler handler)> GetPacketHandlers(ServerType server)
        {
            var assembly = Assembly.GetEntryAssembly();

            return from type in assembly.GetTypes()
                          from method in type.GetMethods()
                          let attribute = method.GetCustomAttributes(typeof(PacketHandlerAttribute), false).Cast<PacketHandlerAttribute>().FirstOrDefault()
                          where attribute?.Server == server
                          select (attribute, (PacketHandler)method.CreateDelegate(typeof(PacketHandler)));
        }