代码之家  ›  专栏  ›  技术社区  ›  Stefan Monov

旧API要求以字符串形式传递回调名称。我可以通过扩展方法来改进这个API吗?

  •  2
  • Stefan Monov  · 技术社区  · 15 年前

    我面临的是一个传统API,它不使用.NET事件,而是要求我这样做:

    // (first arg is System.Object, second arg is string, myFoo is of type Foo)
    myFoo.AddCallback(this, "DoSomething(int)");
    

    此API要求 DoSomething 是上的实例方法 this

    有没有一种方法可以强制这个API以类型安全的方式使用?

    我想为Foo编写一个扩展方法,它允许我使用.NET委托调用AddCallback,而不是使用接收方签名对。我在想象这样的事情:

    // extension method definition
    public static void AddCallback(this Foo foo, Action action)
    {
        foo.AddCallback(
            FigureOutReceiverOf(action),    // ?
            FigureOutSignatureOf(action));  // ?
    }
    
    public static void AddCallback<T>(this Foo foo, Action<T> action)
    { ... } // and so on, for up to, say, 10 type-arguments
    
    // usage:
    myFoo.AddCallback(DoSomething)
    // or even a lambda:
    myFoo.AddCallback((i) => Console.WriteLine(i));
    

    如果有可能通过一个扩展方法黑客做到这一点,它将使我的生活更好。另外,考虑到C#的能力,我只想知道是否有可能。

    1 回复  |  直到 15 年前
        1
  •  3
  •   Jon Skeet    15 年前

    使用lambda将是一个棘手的问题——如果它捕获局部变量,它将最终成为另一个类中的一个方法。当然,您可以检测到这一点,但这并不是编译时安全的。

    一定地 Action Delegate ,或方法组转换不起作用。。。尽管你还可以打电话

    myFoo.AddCallBack(new Action<int>(MyMethodName));
    

    另一种方法是产生一堆重载:

    public static void AddCallback(this Foo foo, Action action)
    
    public static void AddCallback<T>(this Foo foo, Action<T> action)
    
    public static void AddCallback<T1, T2>(this Foo foo, Action<T1, T2> action)
    

    Func .

    还有一个潜在的问题,就是传递一个带有多个动作的委托。。。同样,您可以在编译时检查这个。最后,您可能需要检查 Target 委托的名称与 foo 参数。

    相当地 直截了当。你使用 Delegate.Method 属性,并从中可以获得名称和参数类型。如果图书馆需要 "int" 而不是 "System.Int32"