构造一个接受方法组的流畅API方法

本文关键字:方法 API 一个 | 更新日期: 2023-09-27 18:18:54

我正在尝试构建一个接受方法指示的流畅风格的API。我想要实现的可以用这个(无效的)代码示例来描述:

public class SampleBuilder
{
    public void Method<T>(Expression<Func<T, Delegate>> func) { }
    // for the sake of this example this method doesn't have a return value
}
public class Sample
{
    public void SomeMethod(int some, int arbitrary, int agruments) { }
}
public class SampleConfig
{
    public void Config()
    {
        new SampleBuilder().Method<Sample>(x => x.SomeMethod);
    }
}

问题是编译器明显抱怨x.SomeMethod表示一个方法组。我的API既不能假定实际的实例,也不能假定实际的方法签名。这将在运行时决定。

您如何解决这种情况,以提供一个易于使用的API,让用户指定一个方法组?


背景:最终的用法将是这样的:

config.Transition().From(v1def, v1 => v1.ExitMethod).To(v2def, v2 => v2.EntryMethod);

其中To()From()接受视图及其入口/出口方法的定义。在上面的特定示例中,v1def表示视图定义类,而v1表示实际视图类。在一天结束时,一个新的过渡被构造并添加到config中。

构造一个接受方法组的流畅API方法

不幸的是,根本没有办法将方法组作为参数传递。据我所知,CLR(以及各种语言和介于两者之间的一切)不允许传递本质上是无类型委托的东西……而且由于方法重载,必须考虑由一个方法组名表示具有不同签名的多个委托的情况。

因为我不知道视图定义和视图实例类是如何结构化或实现的细节,所以我能做的最好的事情就是建议通过使用属性来使用AOP。如果它适用于您的建筑,我强烈建议您考虑一下;您可以用自定义属性装饰您的入口和出口方法,并在配置类中使用这些装饰。

如果您的体系结构不适合用AOP进行扩展,那么您剩下的唯一选择就是使用弱类型的解决方案,在编写配置时使用字符串,并在读取这些字符串时使用大量反射。我知道它看起来不像。net中大多数其他流畅的api,但这真的那么糟糕吗?

config.Transition().From(v1def, "ExitMethod").To(v2def, "EntryMethod");

其中一种方法是添加

public void SomeMethod() { }

,并更改SampleBuilder。方法签名到

public void Method<T>(Expression<Func<T, Action>> func) { }

这种方式可以捕获所需方法的名称(通过传递转换为委托实例的方法组)并选择适当的重载