多个类的通用方法 [英] Generic method on multiple classes
问题描述
嘿,
我有很多有道具的课程,需要某种机制等待房产改变。
想象一下:
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屋!