我正在尝试将用java编写的SDK移植到C#。
在这个软件中,有许多“处理程序”接口有几种方法(例如:attemptSomethingHandler
带success()
和几种不同的故障方法。然后在调用类中匿名实现和实例化该接口,并将其传递给attemptSomething
类的SomethingModel
方法。这是一个异步方法,有几个地方可能会失败或调用另一个方法(传递处理程序)。这样,attemptSomethingHandler
的匿名实现可以引用调用attemptSomething
的类中的私有方法。
在C#中,无法匿名实现接口。我可以显式地实现一个新类,但是这个实现对于这个调用类来说是唯一的,而不是用于其他任何东西。更重要的是,我无法访问调用类中的私有方法,这是我需要的,也不想公开。
基本上,我需要根据SomethingModel
类方法中的内容运行调用类中的不同代码。
我一直在阅读代理,但这需要传递尽可能多的委托,因为处理程序界面中有方法(据我所知)。 在C#中执行此操作的适当方法是什么?我觉得我错过了一个非常常见的编程策略。必须有一种简单,干净的方式来构建和解决这个问题。
答案 0 :(得分:10)
在C#中,我们没有像Java这样的匿名类型。您可以创建一个包含如下字段的匿名类型:
var myObject = new { Foo = "foo", Bar = 1, Quz = 4.2f }
但是这些方法不能放在其中,并且只能通过使用object
或dynamic
传递给方法(因为它们在编译时没有类型,它们是由编译器AFAIK生成的)
而在C#中,我们使用,如你所说,委托或lambdas。
如果我理解你的泡菜,你可以实现一个嵌套的私有类,如下所示:
interface IMyInterface
{
void Foo();
}
class MyClass
{
public void Bar()
{
var obj = new MyInterface();
obj.Foo();
}
private class MyInterface : IMyInterface
{
public void Foo()
{
// stuff
}
}
}
现在MyClass
可以创建实现MyInterface
的{{1}}实例。正如评论员所提到的,IMyInterface
可以访问MyInterface
的成员(尽管您肯定希望尝试并坚持使用这两种类型的可公开访问的成员)。
这封装了“匿名”类(在这里使用Java术语使其更简单)并且还意味着您可能将MyClass
作为MyInterface
返回,而其余软件将不是聪明。这实际上是一些抽象工厂模式的工作原理。
基本上,我需要根据SomethingModel类方法中的操作,从调用类中运行不同的代码。
这种混合气味。哦,亲爱的!
听起来像你的特定问题可以使用重构。在C#中你可以使用事件来解决这个问题(注意:可以,不应该)。只需为您的方法的每个“分支”点设置一个事件。但是,我必须说,这确实使您的解决方案更难以设想和维护。
但是我建议你以一种不需要像这样的重型耦合的方式构建你的解决方案。
您也可以尝试使用Pipeline模型,但我不确定如何自己实现。我知道jetty(或者它是Netty?JBOSS的NIO for Java)当然使用了类似的模型。
您可能会发现抛出一些单元测试以测试您的类的预期功能将使您更容易构建解决方案(TDD)。
答案 1 :(得分:10)
使用代表:
void AttemptSomethingAsync(Action onSuccess, Action<string> onError1, Action onError2 = null) {
// ...
}
// Call it using:
AttemptSomethingAsync(onSuccess: () => { Yes(); }, onError1: (msg) => { OhNo(msg); });
或者,使用班级
class AttemptSomethingHandler {
Action OnSuccess;
Action<string> OnError1;
Action OnError2;
}
void AttemptSomethingAsync(AttemptSomethingHandler handler) {
// ...
}
// And you call it like
AttemptSomethingAsync(new AttemptSomethingHandler() {
OnSuccess = () => { Yes() };
});
或事件
public delegate void SuccessHandler();
public delegate void ErrorHandler(string msg);
class SomethingModel {
public event SuccessHandler OnSuccess;
public event ErrorHandler OnError1;
public void AttemptSomethingAsync() {
// ...
}
}
// Use it like
var model = new SomethingModel();
model.OnSuccess += Yes;
model.AttemptSomethingAsync();
private void Yes() {
}
答案 2 :(得分:1)
您可以使用嵌套类来模拟匿名类,但是为了以与Java相同的方式使用嵌套类,您需要将引用传递给外部类。在Java中,默认情况下所有嵌套和匿名类都具有此功能,而只有静态类不具有此功能。
interface IMyInterface
{
void Foo();
}
class MyClass
{
public void Bar()
{
IMyInterface obj = new AnonymousAnalog(this);
obj.Foo();
}
private class AnonymousAnalog : IMyInterface
{
public void Foo(MyClass outerThis)
{
outerThis.privateFieldOnOuter;
outerThis.PrivateMethodOnOuter();
}
}
...
}