Reputation: 91
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
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
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)
{
}
}
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