【问题标题】:How to reimplement Java listeners with anonymous classes in C#如何在 C# 中使用匿名类重新实现 Java 侦听器
【发布时间】:2014-09-20 15:41:29
【问题描述】:

我正在尝试在 C# 中复制我的 Java 代码,我想知道如何在 C# 中复制此 Java 功能。

Util.java

public class Util
{
    public void function(String s, final SetAvailabilityStatusListener setStatusListener)
    {
        // ....
    }

    public static interface SetAvailabilityStatusListener {
        public void setAvailabilityStatus(Status status);
    }
}

Activity.java

public class Activity
{
    public void anotherFunction()
    {
        util.function("name", new SetAvailabilityStatus()
            {
                @Override
                public void setAvailabilityStatus(Status status) {
                    loginSetAvailabilityStatus(status);
                }
            }
    }       
}

【问题讨论】:

标签: java c# interface listener


【解决方案1】:

使用委托。它们用于 C# 而不是实现接口的 Java 匿名类。

public class Util
{
    public void Function(String s, Action<Status> setStatusListener)
    {
        // ....
        setStatusListener("myStatus");
    }
}

public class Activity
{
    private Util util = new Util();
    public void AnotherFunction()
    {
        util.Function("name", status => LoginSetAvailabilityStatus(status));
    }

    public void LoginSetAvailabilityStatus(string status){
        //do something with status
    }


}

【讨论】:

    【解决方案2】:

    我找不到合适的副本,所以:

    1. C# 没有像 Java 那样的匿名类,但没有人阻止您手动创建所需的侦听器类

    public class Util
    {
        public void Function(String s, ISetAvailabilityStatusListener setStatusListener)
        {
            // ....
        }
    
        public interface ISetAvailabilityStatusListener {
            public void SetAvailabilityStatus(Status status);
        }
    }
    
    public class Activity
    {
        private class MySetAvailabilityStatusListener: Util.ISetAvailabilityStatusListener
        {
            public void SetAvailabilityStatus(Status status) 
            {
                // do your handling, but nested classes have some differences with anonymous Java classes, so it may require additional infrastructure.
            }
        }
    
        public void AnotherFunction()
        {
            utilObj.Function("name", 
                new MySetAvailabilityStatusListener())
        }       
    }
    

    就是所谓的observer design pattern(只是没有注销方法!!)。

    2. 正如@AndreySarafanov 已经建议的那样,您可以使用Action Delegates 和lambda expressions

    public class Util
    {
        public void Function(String s, Action<Status> statusChangeListener)
        {
            // ....
        }
    }
    
    public class Activity
    {
        public void AnotherFunction()
        {
            utilObj.Function("name", 
                (status) => 
                {
                    loginSetAvailabilityStatus(status);
                }
        }       
    }
    

    3. C# 有另一种更简单的机制来处理事件处理(订阅)机制 - events and delegates

    public class StatusEventArgs : EventArgs
    {
        //...
    }
    
    public class Util
    {
        public void SomeFunction()
        {
            // ....
            if (this.OnAvailabilityChanged != null)
                OnAvailabilityChanged(this, new StatusEventArgs(status));
        }
    
        public event EventHandler<StatusEventArgs> OnAvailabilityChanged
    }
    
    public class Activity
    {
        public void AvailabilityStatusChangedHandler(object sender, EventArgs<Status> eventArgs) 
        {
        }
    
        public void AnotherFunction()
        {
            utilObj.OnAvailabilityChanged += this.AvailabilityStatusChangedHandler;
        }       
    }
    

    它不允许你将 name 属性与事件处理程序相关联,你可以通过特殊的注册方法来克服它,但它会降低事件的可用性,所以你应该坚持另一种解决方案。

    【讨论】:

    • 我采用了@AndreySarafanov 提供的解决方案,但我相信您分享的信息对我在这个项目中的推进很有用。非常感谢
    • 嗨。经过一番挣扎,我发现您的第三种方法最适合我的用例。但是当我使用App.Current.Resources["ResourceName"] 时,它会给出“无效的跨线程访问。”错误。我实际上是从 AsyncCallback 函数调用它。 public void UserAvailabilityCallback(IAsyncResult ar)。据我所知,这在单独的线程上运行。你能建议一个修复吗?如果我在某处做错了,请纠正我。我正在使用Deployment.Current.Dispatcher 来解决这个问题。可以做其他事情来代替这个吗?
    • @PratPor 这是另一个与此问题没有直接关系的问题,因此您可能应该将其作为一个全新的问题提出 - 这个问题已经达到了它的目标。请阅读stackoverflow.com/questions/8240490/…,然后再询问以更好地了解可能的问题和解决方案。
    • 我认为第一个选项是一种更有用的方法,因为它可以更好地处理多个接口方法的情况,并且还允许您维护从 Java 到 C# 的接口(委托不能代替接口一般)。
    • @DaveDoknjas 是的,代表可能有点被嘲笑地称为穷人的观察者模式。它们是 UI 事件处理(在一个 UI 元素内)的有效解决方案,但对于更复杂的事情,您最终会使用更复杂的解决方案。
    猜你喜欢
    • 2019-04-12
    • 2015-04-24
    • 1970-01-01
    • 2023-03-12
    • 1970-01-01
    • 2014-05-11
    • 1970-01-01
    • 1970-01-01
    • 2013-06-27
    相关资源
    最近更新 更多