多个类的通用方法 [英] Generic method on multiple classes

查看:91
本文介绍了多个类的通用方法的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

嘿,



我有很多有道具的课程,需要某种机制等待房产改变。

想象一下:



Hey,

I got many classes that have a prop and need some sort of mechanism to wait for the property to change.
Imagine this:

class A
{
    public event Action OnChanged;
    public int Data { get; set; }
    public void DoWork() { /* after some time will update "Data" property */ }
}
class B
{
    public event Action OnChanged;
    public int Data { get; set; }
    public void DoWork() { /* after some time will update "Data" property */ }
}
class C
{
    public event Action OnChanged;
    public int Data { get; set; }
    public void DoWork() { /* after some time will update "Data" property */ }
}





现在我需要在将来创建更多这些类,我需要一些通用的方法/扩展来等待属性数据的更改。

我知道我可以用事件做到这一点然后使用Thread.Sleep,但它不是最好的编码方式,因为睡眠占用了一个线程。

另一种方法是使用这样的TaskCompletionSource:





Now I will need to create more of these classes in the future and I need some generic method/extension to wait for the property "Data" change.
I know I can do this with events and then using Thread.Sleep, but it's not the best way of coding since sleeping takes up a thread.
Another way was to use the TaskCompletionSource like this:

// this is for class A only... I would need to copy paste this for B and C
static class Extension
    {
        public static Task<object> ToTask(this A manager)
        {
            TaskCompletionSource<object> taskCompletionSource = new TaskCompletionSource<object>(TaskCreationOptions.AttachedToParent);

            Action onChanged = null;

            onChanged = () =>
            {
                manager.OnChanged -= onChanged;
                taskCompletionSource.SetResult(null);
            };

            manager.OnChanged += onChanged;

            return taskCompletionSource.Task;
        }
    }





上面允许在主方法中有这个:





The above allows the have this in the main method:

static void Main(string[] args)
{
    A instance = new A();
    instance.DoWork().ToTask().Wait();

}





...但是我必须为我创建的每个新类编写扩展名,这不是我想要的东西。有人知道如何概括这个吗?



谢谢!



我有什么尝试过:



检查上面的代码 - 试着在这里安静一些。



...But then I would have to write the extension for every new class i create, which is not something I want. Anyone know of a way how to generalize this?

Thanks!

What I have tried:

Check the code above - tried quiet a few things here.

推荐答案

三个显而易见的选项:



1)从定义事件的基类派生,并声明扩展方法以获取该基类的实例。

Three obvious options:

1) Derive from a base class which defines the event, and declare your extension method to take an instance of that base class.
abstract class ManagerBase
{
    public event EventHandler Changed;
    
    protected void OnChanged()
    {
        Changed?.Invoke(this, EventArgs.Empty);
    }
}

class A : ManagerBase { ... }
class B : ManagerBase { ... }
class C : ManagerBase { ... }

...

public static Task ToTask(this ManagerBase manager) { ... }





2)实现定义事件的接口,并声明扩展方法以获取该接口的实例:



2) Implement an interface which defines the event, and declare your extension method to take an instance of that interface:

interface IManager
{
    event EventHandler Changed;
}

class A : IManager
{
    public event EventHandler Changed;
    
    private void OnChanged()
    {
        Changed?.Invoke(this, EventArgs.Empty);
    }
    
    ...
}

...

public static Task ToTask(this IManager manager) { ... }





3)传递方法来附加和分离事件处理程序作为操作:



3) Pass in the methods to attach and detach the event handler as actions:

public static Task ToTask<T>(this T manager, Action<T, EventHandler> addHandler, Action<T, EventHandler> removeHandler)
{
    var taskCompletionSource = new TaskCompletionSource<bool>(TaskCreationOptions.AttachedToParent);
    
    EventHandler onChanged = null;
    
    onChanged = (sender, args) =>
    {
        removeHandler((T)sender, onChanged);
        taskCompletionSource.TrySetResult(true);
    };
    
    addHandler(manager, onChanged);
    
    return taskCompletionSource.Task;
}


我不确定你想要达到的目的......

1st:

如果你有许多类通用的东西你可以将它们编码成一个baseClass并让所有其他类从它派生出来

第二名:

你不要我需要编写一个Task来检查你的类的属性是否发生了变化。这可以很容易地在您的物业的Setter(-Method)内完成 - 在这里您可以举起活动



I'm not sure what you try to achieve ...
1st:
if you have things which are common to many classes you could code them into one baseClass and let all other classes derive from it
2nd:
you don't need to code a Task to check if a Property of your class changes. This could very easily done inside the Setter(-Method) of your Property - here you can raise the Event

Property Test As Double
     Get
         Return my_Test
     End Get
     Set(ByVal value As Double)
         if value <> my_Test then RaiseEvent Changed
         my_Test = value
     End Set
 End Property
 Private my_Test As Double = 1.0







public double Test {
	get { return my_Test; }
	set {
		if (value != my_Test)
			if (Changed != null) {
				Changed();
			}
		my_Test = value;
	}
}
private double my_Test = 1.0;


这篇关于多个类的通用方法的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆