简体   繁体   English

在 C# 中调用具有方法属性的非静态方法

[英]Call non-static methods with method attributes in C#

I currently have a working system that when a static method has an event attribute and a single param of type Event then it can be called by the EventSystem.我目前有一个工作系统,当 static 方法具有事件属性和事件类型的单个参数时,它可以由 EventSystem 调用。

Example method示例方法

[EventAtribute]
public static void thisIsAnEventHandler(Event ev)
{
  print(ev.ToStrring());
}

When I call this function it gets all methods with this event type and calls it, MethodInfo.Invoke takes a obj of null as all the method are static.当我调用此 function 时,它会获取具有此事件类型的所有方法并调用它, MethodInfo.Invoke 采用 null 的 obj,因为所有方法都是 ZA81259CEF8E959C624DF1D456E5D3297

public static void callMethodsWithEvent(Event ev)
        {
            // triggers when initEventSystem has not been called
            Debug.Assert(_eventMethods != null);
            
            var methods = _eventMethods
            .Where(x => x.GetParameters()[0].ParameterType == ev.GetType())
            .Where(x => x.GetParameters().Length == 1)
            .Where(x => x.IsStatic);

            foreach (var method in methods) // iterate through all found methods
            {
                method.Invoke(null, new object[] {ev});
            }
        }

How all methods are stored on startup所有方法在启动时如何存储

public static void initEventSystem()
        {
            _eventMethods = AppDomain.CurrentDomain
                .GetAssemblies() // Returns all currenlty loaded assemblies
                .SelectMany(x => x.GetTypes()) // returns all types defined in this assemblies
                .Where(x => x.IsClass) // only yields classes
                .SelectMany(x => x.GetMethods())
                .Where(x => x.GetCustomAttributes(typeof(EventAtribute), false).FirstOrDefault() != null)
                .ToList();
        }

Even though this system work great it only works static methods.即使这个系统运行良好,它也只适用于 static 方法。 I know I need to pass a object reference into the Invoke method but I want to be able to create events and and let any method with that event be called without me having to think about it.我知道我需要将 object 引用传递给 Invoke 方法,但我希望能够创建事件并让带有该事件的任何方法被调用,而无需我考虑它。

So I think what I need is to be able to get all object with this method signature and call all of those methods in all of those objects individually.所以我认为我需要的是能够使用此方法签名获取所有 object 并在所有这些对象中单独调用所有这些方法。 Is there any way to do this without walking through the heap.有没有办法在不遍历堆的情况下做到这一点。

Thanks.谢谢。

With the comments above, I suggest a solution such as the following (just a broad idea, the implementation will need more details).有了上面的评论,我建议了一个如下的解决方案(只是一个广泛的想法,实现需要更多细节)。 And yes, an interface only offers methods, no implementation.是的,接口只提供方法,没有实现。 But that's exactly the same as with a delegate, it is also only a definition on how to call a certain method, but not the implementation itself.但这和委托完全一样,也只是定义了如何调用某个方法,而不是实现本身。 An interface can actually be seen as a collection of delegates joined together.接口实际上可以看作是连接在一起的委托集合。

Create an attribute that can be attached to classes, telling your event system that these classes can receive certain events:创建一个可以附加到类的属性,告诉您的事件系统这些类可以接收某些事件:

    /// <summary>
    /// Declares the visibility of a component.
    /// </summary>
    [AttributeUsage(AttributeTargets.Class, AllowMultiple = false, Inherited = true)]
    public sealed class InterfaceSupportAttribute : Attribute
    {
        private Type[] m_supportedInterfaces;

        public InterfaceSupportAttribute()
        {
            m_supportedInterfaces= new Type[0];
        }

        public Type[] SupportedInterfaces
        {
            get => m_external;
            set => m_external = value.Distinct().ToArray();
        }
    }

Used as follows:使用如下:


public interface IMyFunctionality
{
    public void Foo();
}

[InterfaceSupportAttribute(SupportedInterfaces = new[] {typeof(IMyFunctionality)}) 
public class MyClass : IMyFunctionality
{
   public MyClass() {...}
   public void Foo() {...}
}

Then, somewhere else in the code:然后,在代码的其他地方:


MyClass c = new MyClass();
RegisterType(c);

And the RegisterType function extracts the attribute and retains a reference to the class. RegisterType function 提取属性并保留对 class 的引用。 Another function is then used to query all classes that implement IMyInterface .然后使用另一个 function 查询所有实现IMyInterface的类。 You can implement these functions yourself or use an existing Dependency Injection Framework , such as NInject.您可以自己实现这些功能,也可以使用现有的依赖注入框架,例如 NInject。 These offer exactly the functions to register classes (and their interfaces) and query the registered classes for a certain interface.这些提供了注册类(及其接口)和查询注册类以获取特定接口的功能。

Note: I have never worked with unity, but I would actually assume that it already includes such a dependency injection framework, as a lot of larger software packages use it in one form or the other.注意:我从未使用过 unity,但我实际上假设它已经包含这样的依赖注入框架,因为许多较大的软件包以一种或另一种形式使用它。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM