使用C#的匿名接口实现

时间:2019-06-17 10:58:12

标签: c# interface anonymous-class

我有一些界面:

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#中使用匿名类吗?如果没有,在这种情况下该怎么办?

提前谢谢。问候...

2 个答案:

答案 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仍然活着。