如何在强类型的接口上引用方法名称

时间:2012-03-05 12:22:04

标签: c# reflection interface strongly-typed-view strong-typing

很抱歉,如果已经回答了这个问题,但我认为我实际上缺乏正式的教育来正确地提出这个问题,因此也没有正确的标准来成功地搜索它。

我有一个API,它有几个几乎完全相同的调用,但是使用不同的方法对不同的输入对象起作用,但总是形成相同的接口。我想采取削减&从API方法调用进程中粘贴方面,以便公共代码在所有方法调用中完成相同的操作。我已经设法使用泛型为输入和输出对象获得一个有效的解决方案,并且正在引用要从字符串调用的方法名称。我想引用强类型方法而不是基于字符串的方法,因此在重新分解时重命名方法名称不会使方法名称的“魔术”字符串等待在运行时爆炸。

以下是我想要实现的非常简化的版本。

class ARequest { };
class AResponse { };
class BRequest { };
class BResponse { };

interface IWorker
{
    AResponse DoA(ARequest aRequest);
    BResponse DoB(BRequest bRequest);
}
class Worker : IWorker
{
    public AResponse DoA(ARequest aRequest)
    {
        return new AResponse();
    }
    public BResponse DoB(BRequest bRequest)
    {
        return new BResponse();
    }
}

class Program
{
    static void Main(string[] args)
    {
        // current concrete copy & paste implementation
        var a1 = API.DoA(new ARequest { });
        var b1 = API.DoB(new BRequest { });
        // new generic implementation
        var a2 = API.DoA2(new ARequest { });
        var b2 = API.DoB2(new BRequest { });
    }
}

static class API
{
    // current concrete copy & paste implementation
    public static AResponse DoA(ARequest aRequest)
    {
        // lots of common code for logging & preperation
        var worker = GetWorker();
        return worker.DoA(aRequest);
    }
    public static BResponse DoB(BRequest bRequest)
    {
        // lots of common code for logging & preperation
        var worker = GetWorker();
        return worker.DoB(bRequest);
    }
    private static IWorker GetWorker()
    {
        return new Worker();
    }
    // new generic implementation Attempt
    public static AResponse DoA2(ARequest aRequest)
    {
        return DoGen<ARequest, AResponse>(aRequest, "DoA"); // how to make references to DoA and DoB methods on the IWorker strongly typed?
    }
    public static BResponse DoB2(BRequest bRequest)
    {
        return DoGen<BRequest, BResponse>(bRequest, "DoB"); // how to make references to DoA and DoB methods on the IWorker strongly typed?
    }
    public static TResponse DoGen<TRequest, TResponse>(TRequest requestObj, string methodname)
        where TRequest : class
        where TResponse : class
    {
        // lots of common code for logging & preperation
        var worker = GetWorker();
        var mi = worker.GetType().GetMethod(methodname);
        var result = mi.Invoke(worker, new Object[] { requestObj });
        return result as TResponse;
    }

}

4 个答案:

答案 0 :(得分:2)

方法名称的“magic”字符串更改为委托上的委托

  public static AResponse DoA2(ARequest aRequest)
  {
    return DoGen<ARequest, AResponse>(aRequest, worker => worker.DoA);
  }
  public static BResponse DoB2(BRequest bRequest)
  {
    return DoGen<BRequest, BResponse>(bRequest, worker => worker.DoB); 
  }
  public static TResponse DoGen<TRequest, TResponse>(TRequest requestObj, 
       Func<IWorker, Func<TRequest, TResponse>> methodRef)
    where TRequest : class
    where TResponse : class
  {
    // lots of common code for logging & preparation 
    var worker = GetWorker();
    var method = methodRef(worker);

    return method(requestObj);
  }

答案 1 :(得分:1)

函数功能&LT; xRequest,xResponse&gt;可能会做你想要的:

        var a1 = new Func<ARequest, AResponse>(API.DoA);
        var b1 = new Func<BRequest, BResponse>(API.DoB);
        var a2 = new Func<ARequest, AResponse>(API.DoA2);
        var b2 = new Func<BRequest, BResponse>(API.DoB2);
        a1.Invoke(new ARequest { });
        b1.Invoke(new BRequest { });
        a2.Invoke(new ARequest { });
        b2.Invoke(new ARequest { }); // fails at compile time

答案 2 :(得分:0)

为方法添加委托:

    public delegate TResponse DoXDelegate<in TRequest, out TResponse>(TRequest request);

    public static TResponse DoGen<TRequest, TResponse>(TRequest requestObj, DoXDelegate<TRequest, TResponse> method)
        where TRequest : class
        where TResponse : class
    {
        // lots of common code for logging & preperation
        var worker = GetWorker();
        /*var mi = worker.GetType().GetMethod(methodname);
        var result = mi.Invoke(worker, new Object[] { requestObj });
        return result as TResponse;*/
        return method.Invoke(requestObj);
    }

答案 3 :(得分:0)

像这样使用 Func<TRequest, TResponse>

编辑:该解决方案示例仅在工作对象来自哪里无关紧要时才可用。

// new generic implementation Attempt
public static AResponse DoA2(ARequest aRequest)
{
  return DoGen<ARequest, AResponse>(aRequest, DoA); // how to make refreces to DoA and DoB methods strongly typed?
}

public static BResponse DoB2(BRequest bRequest)
{
  return DoGen<BRequest, BResponse>(bRequest, DoB); // how to make refreces to DoA and DoB methods strongly typed?
}

public static TResponse DoGen<TRequest, TResponse>(TRequest requestObj, Func<TRequest, TResponse> func)
  where TRequest : class
  where TResponse : class
{
  // lots of common code for logging & preperation
  var result = func(requestObj);
  return result as TResponse;
}