1

我正在尝试公开这样的 API,我执行以下操作

RegisterCallback<T>(Action<T> func)
{
    someObj.FuncPointer = func;
}

稍后,我调用 func(obj) .. 并且 obj 是用户所说的 T 类型。

更具体的例子:

var callbackRegistrar = new CBRegistrar();
callbackRegistrar.RegisterCallback<ISomeClass>(SomeFunc);

public static void SomeFunc(ISomeClass data)
{
    //
}

编辑:所以我可能不清楚,所以我将添加更多代码:

我只想制作 CBRegistrar 的“一个”对象,并将其与许多回调连接,如下所示:

var callbackRegistrar = new CBRegistrar();
callbackRegistrar.RegisterCallback<ISomeClass>(SomeFunc);
callbackRegistrar.RegisterCallback<ISomeOtherClass>(SomeFunc2);
...

事实上,上面的代码是通过反映插件目录来调用的。

用户将其放入他们的代码中 -->

public static void SomeFunc(ISomeClass data)
{
    //
}

public static void SumFunc2(ISomeOtherClass data)
{
    //
}

在我看来,这似乎是不可能使用泛型等的。看起来我可能需要做的是创建一个名为 IPlugin 或其他东西的接口,并要求用户执行此操作..

[PluginIdentifier(typeof(ISomeClass))]
public static void SomeFunc(IPluginData data)
{
    var castedStuff = data as ISomeClass; // ISomeClass inherits from IPluginData
}

似乎要求用户做我们应该照顾的事情,但无论如何......

4

3 回答 3

0

回调函数在 C# 中使用不多。它们已被更优雅且更易于使用的事件所取代。

class CBRegistrar
{
    public delegate void ActionRequiredEventHandler(object sender, ISomeClass e); 

    public event ActionRequiredEventHandler ActionRequired;
    void RaiseActionRequiredEvent(ISomeClass parm)
    {
       if ( ActionRequired != null)
       {
           ActionRequired(this, parm);
       }
    }

}

class APIConsumer
{
     var callbackRegistrar = new CBRegistrar();
     public APIConsumer()
     {

               callbackRegistrar.ActionRequired += SomeFunc;


     }
     public void SomeFunc(object sender, ISomeClass data)
     {

     }

}

如果您仍然想使用回调,您可以使用或多或少的函数指针的委托。

于 2012-05-29T05:21:04.577 回答
0

您需要将Action<T> func其存储在其中。这里需要进行语义检查:如果有人调用RegisterCallback 了两次(使用不同的值),您是要替换回调,还是保留两者?假设后者,someObj可能需要一个event(实际上,这整个 API 可以作为一个事件公开),所以 - 在someObj类中:

public event Action<T> FuncPointer;
private void InvokeCallback(T data) {
    var handler = FuncPointer;
    if(handler != null) handler(data);
}

注意到RegisterCallback可以完全替换,仍然保留数据obj

public event Action<T> Completed {
    add { obj.FuncPointer += value; }
    remove { obj.FuncPointer -= value; }
}

那么用法是:

var callbackRegistrar = new CBRegistrar();
callbackRegistrar.Completed += SomeFunc;
于 2012-05-29T05:21:28.447 回答
0

CBRegistrar 需要是通用的(如果可以保留单个回调类型)或者它可以进行一些内部转换(如果需要注册多个回调类型)。

public class CBRegistrar<T>
{
    private Action<T> callback;
    private Dictionary<Type, object> callbackMap;

    public CBRegistrar()
    {
        this.callbackMap = new Dictionary<Type, object>();
    }

    public void RegisterCallback(Action<T> func)
    {
        this.callback = func;
    }

    public void RegisterGenericCallback<U>(Action<U> func)
    {
        this.callbackMap[typeof(U)] = func;
    }

    public Action<U> GetCallback<U>()
    {
        return this.callbackMap[typeof(U)] as Action<U>;
    }
}

public interface ISomeClass
{
    string GetName();
}

public class SomeClass : ISomeClass
{
    public string GetName()
    {
        return this.GetType().Name;
    }
}

namespace ConsoleApplication
{
    class Program
    {
        static void Main(string[] args)
        {
            var callbackRegistrar = new CBRegistrar<ISomeClass>();

            callbackRegistrar.RegisterCallback(SomeFunc);
            callbackRegistrar.RegisterGenericCallback<ISomeClass>(SomeFunc);

            var someone = new SomeClass();

            callbackRegistrar.GetCallback<ISomeClass>()(someone);
        }

        public static void SomeFunc(ISomeClass data)
        {
            // Do something
            Console.WriteLine(data.GetName());
        }
    }
}
于 2012-05-29T05:36:04.877 回答