【问题标题】:Call method that has a Delegate instance parameter through Reflection C#通过反射 C# 调用具有 Delegate 实例参数的方法
【发布时间】:2020-12-09 09:41:05
【问题描述】:

我在外部程序集中有这个 C# 代码:

namespace Fancy
{
  internal class Foo
  {
    public static void Window(string title, Foo.WindowFunction sceneViewFunc, int order)
    {}
    
    public delegate void WindowFunction(float x, float y);
  }
}

我有我的代码:

class A 
{
  public static void Draw(float x, float y) 
  {
     // impl
  }

  static void Main(string[] args)
  {
     var newWindow = ?;
  }
}

我想像这样调用 Fancy.Foo.Window()

Fancy.Foo.Window("Window Name", new Foo.WindowFunction(A.Draw), 450);

在我的 A 类中通过反射。

我该怎么做?尝试了很多不同的选项都没有成功:/

【问题讨论】:

  • Fancy.Foo.Window("窗口名称", new Foo.WindowFunction(Draw), 450);如果内部类 Foo 更改为类 Foo 会起作用
  • 如果要从其他程序集中调用Foo,为什么要标记internal?你就不能做到public吗?

标签: c# reflection


【解决方案1】:

documentation 定义internal 访问修饰符如下

同一程序集中的任何代码都可以访问类型或成员,但不能从另一个程序集中访问。

无法从程序集外部访问是默认行为和预期行为。但是你可以通过多种方式做到这一点。如果您有权访问外部程序集的源。您可以将当前程序集标记为外部程序集的friend,如下所示并重新编译它。

[assembly: InternalsVisibleTo("<Your assembly name>")]

考虑到您可能无法始终访问外部程序集的源,同样可以使用reflection 通过加载程序集、创建类的实例并获取Non-Public 上的Non-Public 成员@ 来完成。类型。见how to access internal class using reflection。另见other ways to use internal class of another assembly

对外部/第三方程序集使用反射有其自身的注意事项,因为程序集的源可能随时更改,从而破坏您的代码。

【讨论】:

    【解决方案2】:

    下面是代码: ClassLibrary1:

    using System;
    namespace ClassLibrary1
    {
    public class Foo
    {
        public static void Window(string title, WindowFunction sceneViewFunc, int order)
        {
            Console.WriteLine("Foo Window");
        }
    
        public delegate void WindowFunction(float x, float y);
    }
    }
    

    主程序.cs

    using System;
    using static ClassLibrary1.Foo;
    
    namespace Algorithums
    {
    public class Program
    {
         public static void Draw(float x, float y)
         {
            // impl
         }
        public static void Main(string[] args)
        {
            RegisterWindowFunctionActionAndWindow("Window Name", 450);        
            Console.WriteLine("Hello World!");
            Console.ReadLine();
        }
    
        public static void RegisterWindowFunctionActionAndWindow(string WindowName, int order)
        {
            var jsoType = Type.GetType("ClassLibrary1.Foo,ClassLibrary1");
            var jso = Activator.CreateInstance(jsoType);
            var mi = typeof(Program).GetMethod("Draw");
            var d = Delegate.CreateDelegate(typeof(WindowFunction), mi);
            var mi0 = jsoType.GetMethod("Window", new[] { typeof(string), typeof(WindowFunction), typeof(int) });
            mi0.Invoke(jso, new object[] { WindowName, d, order });
        }
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-04-16
      • 1970-01-01
      • 2016-05-26
      • 2016-04-25
      • 2011-01-26
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多