微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

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

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

我目前有一个工作系统,当一个静态方法具有一个事件属性一个 Event 类型的单个参数时,它可以被 EventSystem 调用

示例方法

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

当我调用函数时,它会获取具有此事件类型的所有方法调用它,MethodInfo.Invoke 将 obj 设为 null,因为所有方法都是静态的。

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});
            }
        }

如何在启动时存储所有方法

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();
        }

尽管这个系统工作得很好,但它只适用于静态方法。我知道我需要将一个对象引用传递到 Invoke 方法中,但我希望能够创建事件并让任何具有该事件的方法调用而无需我考虑。

所以我认为我需要的是能够获取具有此方法签名的所有对象并分别调用所有这些对象中的所有这些方法。有没有办法在不遍历堆的情况下做到这一点。

谢谢。

解决方法

根据上面的评论,我提出了如下解决方案(只是一个广泛的想法,实现需要更多细节)。是的,接口只提供方法,没有实现。但这与委托完全相同,它也只是关于如何调用某个方法的定义,而不是实现本身。一个接口实际上可以看作是连接在一起的委托的集合。

创建一个可以附加到类的属性,告诉你的事件系统这些类可以接收某些事件:

    /// <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();
        }
    }

用法如下:


public interface IMyFunctionality
{
    public void Foo();
}

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

然后,代码中的其他地方:


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

RegisterType 函数提取属性并保留对类的引用。然后使用另一个函数查询实现 IMyInterface 的所有类。您可以自己实现这些功能,也可以使用现有的依赖注入框架,例如 NInject。这些提供了注册类(及其接口)和查询某个接口的注册类的功能。

注意:我从来没有使用过 unity,但我实际上假设它已经包含这样一个依赖注入框架,因为许多较大的软件包都以一种或另一种形式使用它。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。