我有一些界面:
interface IServerListener
{
void onServerStarted();
void onSessionStarted();
void onSessionCompleted(List<string> data);
}
还有一些方法,该方法获取该接口的实例以执行方法:
public void start(IServerListener listener)
{
IPEndPoint hostPoint = new IPEndPoint(IPAddress.Parse(getLocalHost()), PORT);
serverSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
serverSocket.Bind(hostPoint);
serverSocket.Listen(5);
listener.onServerStarted(); //Calling
while(true)...
}
当我从主表单类执行此方法(start)时,我想将完全实现该接口的匿名类传递给参数,以使用表单元素:
private void Form1_Load(object sender, EventArgs e)
{
server = new Server();
server.start(new IServerListener()
{
void onServerStarted()
{
rtxtOutput.AppendText("Started... ");
}
void onSessionCompleted(List<string> data)
{
rtxtOutput.AppendText("Session completed: " + String.Join(", ", data));
}
void onSessionStarted()
{
rtxtOutput.AppendText("New session started... ");
}
});
}
但是我不能像在 Java 中那样做。我收到以下消息:
Cannot create an instance of the abstract class or interface 'IServerListener'
因此,我尝试创建实现该接口的单独类,并且已经在那里执行我需要的操作。但是我无法从那里访问使用表单元素:
private class AnonymousIServerListener : IServerListener
{
public void onServerStarted()
{
rtxtOutput.AppendText("Started... ");
//The name 'rtxtOutput' does not exist in the current context
}
public void onSessionCompleted(List<string> data)
{
rtxtOutput.AppendText("Session completed: " + String.Join(", ", data));
//The name 'rtxtOutput' does not exist in the current context
}
public void onSessionStarted()
{
rtxtOutput.AppendText("New session started... ");
//The name 'rtxtOutput' does not exist in the current context
}
}
在没有拐杖的情况下,请告诉我该怎么办。通常可以在 C#中使用匿名类吗?如果没有,在这种情况下该怎么办?
提前谢谢。问候...
答案 0 :(得分:3)
为什么不为此使用Action
...
private void Form1_Load(object sender, EventArgs e)
{
server = new Server();
server.start(new ServerListener()
{ OnServerStarted = () => rtxtOutput.AppendText("Started... ")
, OnSessionCompleted = data =>
{
rtxtOutput.AppendText("Session completed: " + String.Join(", ", data));
}
, OnSessionStarted = () => rtxtOutput.AppendText("New session started... ")
)
);
}
还有ServerListener
:
public class ServerListener : IServerListener
{
void IServerListener.onServerStarted() => OnServerStarted?.Invoke();
void IServerListener.onSessionStarted() => OnSessionStarted?.Invoke();
void IServerListener.onSessionCompleted(List<string> data) => OnSessionCompleted?.Invoke(data);
public Action OnServerStarted { get; set; }
public Action<List<string>> OnSessionCompleted { get; set; }
public Action OnSessionStarted { get; set; }
}
在这里,ServerListener
只是充当连接点的中间件。它本身不会做任何事情。
答案 1 :(得分:2)
这与匿名类型无关。您想将AnonymousIServerListener
与表单分离。确实如此,因为否则,如果没有包含AnonymousIServerListener
的{{1}}实例,您将无法实例化Form1
。
例如,您想要从监听器引发一个事件。给您的界面一个事件:
TextBox rtxtOutput
定义EventArgs:
public interface IServerListener
{
event EventHandler<LogEventArgs> Log;
// ...
}
然后将其添加到您的监听器中:
public class LogEventArgs : EventArgs
{
public string LogText { get; }
public LogEventArgs(string logText)
{
LogText = logText;
}
}
最后,在实例化public class AnonymousIServerListener : IServerListener
{
public event EventHandler<LogEventArgs> Log = delegate { };
public void OnServerStarted()
{
Log.Invoke(new LogEventArgs("Started... "));
}
public void OnSessionCompleted(List<string> data)
{
Log.Invoke(new LogEventArgs("Session completed: " + String.Join(", ", data)));
}
public void OnSessionStarted()
{
Log.Invoke(new LogEventArgs("New session started... "));
}
}
的类中订阅您的事件:
AnonymousIServerListener
但是现在private void Form1_Load(object sender, EventArgs e)
{
server = new Server();
IServerListener listener = new AnonymousIServerListener();
listener.Log += (e) => rtxtOutput.AppendText(e.LogText);
server.start(listener);
}
返回时,您将有一个悬挂的引用,并与Log事件订阅绑定在一起。您将永远无法取消订阅,在您的应用程序生存期的剩余时间内,Form1_Load
仍然活着。