MaZy
MaZy

Reputation: 91

How to get method which got attribute and

Hello I need two things. I saw somewhere something like this

You have a method where you put [Attribute] above and the code adds every method names as string in the list, dictionary whatever. I need it because I want to make network system with RPC and want to check (and define method as function call over the network) on the server and client if same RPC names exists.. if not exists then print error.

Well I found few things like System.AppDomain.CurrentDomain.GetAssemblies(); and MethodInfo[] methods but I don't know how to continue / use it. Very Important. I need to know params too.

As test I made this small thing.

[AttributeUsage(AttributeTargets.Method, AllowMultiple = true)]
public class Navigation : Attribute
{

}

public class MenuNavigator
{
    [Navigation]
    void Next()
    {

    }

    [Navigation]
    void Last(bool bla)
    {

    }
}

Upvotes: 1

Views: 4144

Answers (2)

MaZy
MaZy

Reputation: 91

Sorry for late response but I went other way. You helped me a lot. I am going through all methods which I can find from the assembly. Then I check for RPC definition. That will include even the NetworkBehaviour baseclass.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;

/// <summary>
/// Currently it supports up to 255 RPCs
/// </summary>
[AttributeUsage(AttributeTargets.Method, Inherited = true)]
public class RPC : Attribute
{
    static byte rpcIdCounter = 0;
    //maybe channels
    public byte RpcId { get; private set; }

    public RPC()
    {
        RpcId = rpcIdCounter++;
    }
}

public class NetworkBehaviour
{

    // later network functions
    [RPC] //remote proceure call
    protected void Base()  //example remote call on other computer Move()
    {
    }

    [RPC]
    protected virtual void OverridableBase()
    {
    }

    protected virtual void OverridableNotRPC()
    {
    }
}

class ControlCharacter : NetworkBehaviour
{
    [RPC] //remote proceure call
    void Move()  //example remote call on other computer Move()
    {

    }

    public void DrawHud() // example this will not do remote call
    {

    }
}

class OtherClass : NetworkBehaviour
{
    [RPC]
    void Start()
    {
    }

    [RPC]
    void Stop()
    {
    }

    protected override void OverridableBase()
    {
    }

    [RPC]
    protected override void OverridableNotRPC()
    {
    }

    void NotRPC()
    {
    }
}

public class Program
{
    public static void Main()
    {
        //Console.WriteLine("ControlCharacter ---");
        //var obj = new ControlCharacter();

        //foreach(var m in GetRPCMethods(obj)) {
        //    Console.WriteLine(m.ToString());
        //}

        //Console.WriteLine("OtherClass ---");

        //var other = new OtherClass();
        //foreach(var m in GetRPCMethods(other)) {
        //    Console.WriteLine(m.ToString());
        //}

        //Console.WriteLine("NetworkBehaviour ---");
        //var next = (typeof(NetworkBehaviour));
        //foreach(var m in next.GetType().GetMethods(BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance ).Where(e => e.GetCustomAttribute<RPC>() != null)) {
        //    Console.WriteLine("NetworkBehaviour: " + m.ToString());
        //}
        //Console.WriteLine("");

        var assembly = Assembly.GetExecutingAssembly();
        var Types = assembly.GetTypes();

        var names = (from type in Types
                     from method in type.GetMethods( BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance ).Where(e => e.GetCustomAttribute<RPC>() != null)
                     select type.FullName + ":" + method.Name).ToList();

        foreach(var methodNames in names) {
            Console.WriteLine(methodNames);
        }


    }

    //public static IEnumerable<MethodInfo> GetRPCMethods(NetworkBehaviour obj)
    //{
    //    return obj.GetType()
    //        // Remove BindingFlags.DeclaredOnly to include method from base class      
    //              .GetMethods(BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance).Where(e => e.GetCustomAttribute<RPC>() != null);
    //}
}

Output:

NetworkBehaviour:Base
NetworkBehaviour:OverridableBase
ControlCharacter:Move
ControlCharacter:Base
ControlCharacter:OverridableBase
OtherClass:Start
OtherClass:Stop
OtherClass:OverridableBase
OtherClass:OverridableNotRPC
OtherClass:Base

Upvotes: 0

Aydin
Aydin

Reputation: 15294

It sounds like you're asking how to use reflection to see whether a method has a specific attribute or not, you do it like this.

void Main()
{
    MenuNavigator navigator = new MenuNavigator();

    Navigation methodNextAttribute = navigator.GetType()
                                              .GetMethod("Next")
                                              .GetCustomAttribute<Navigation>();

    Console.WriteLine ("Method `Next` has the `Navigation` attribute?\n> {0}\n", methodNextAttribute != null);
    // -------- Output -------- 
    // Method `Next` has the `Navigation` attribute?
    // > True

    Navigation methodLastAttribute = navigator.GetType()
                                              .GetMethod("Last")
                                              .GetCustomAttribute<Navigation>();

    Console.WriteLine ("Method `Last` has the `Navigation` attribute?\n > {0}\n", methodLastAttribute != null);  
    // -------- Output -------- 
    // Method `Last` has the `Navigation` attribute?
    // > False

}

[AttributeUsage(AttributeTargets.Method, AllowMultiple = true)]
public class Navigation : Attribute
{
}

public class MenuNavigator
{
    [Navigation]
    public void Next()
    {
    }

    public void Last(bool bla)
    {
    }
}

Edit

In response to the comment you made under your original question...

void Main()
{
    ControlCharacter control = new ControlCharacter();
    control.GetType()
           .GetMethods(BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly)
           .Where(method => method.GetCustomAttribute<RPC>() == null)
           .Select(method => method.Name)
           .ToList()
           .ForEach(Console.WriteLine);
}

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

public class NetworkBehavior
{
}

public class ControlCharacter : NetworkBehavior
{
    [RPC] 
    public void Move() { }

    public void DrawHud() { }
}

Upvotes: 2

Related Questions