在财产上发射一个事件/function? (C#)

我正在使用一个我无法编辑的类,它有一个属性(一个布尔值),当它发生变化时被告知是很好的,我无法编辑属性获取或设置,因为我从一个导入类。 DLL(我没有代码)。

如何创建在更改属性时触发的事件/函数?

额外
它只在自己的类中更改,直接更改为底层的私有变量。

例如

private bool m_MyValue = false; public bool MyValue { get { return m_MyValue; } } private void SomeFunction() { m_MyValue = true; } 

你不能,基本上……不是没有使用类似调试器API的东西在执行时注入代码并修改原始库的IL(我不推荐这些解决方案中的任何一个;除了它可能违反的任何其他内容图书馆的许可证)。

基本上,如果属性不支持通知,则它不支持通知。 您应该寻找一种不同的方式来解决您的问题。 (轮询工作,例如?)

你不能直接这样做[正如Jon Skeet所说],除非它是虚拟的,否则你可以拦截类的所有实例创建,并且不会改变影响propget真实“价值”的支持字段。

暴力破解的唯一方法是使用Mono.Cecil或MS CCI 在Cecil上使用这个DimeCast来设置道具设置器。 (或PostSharp)

但是,这不会捕获对支持字段的内部更改(如果有的话)。 (这就是包装可能不起作用的原因)。

更新:鉴于您的更新,您肯定试图捕获基础字段更改,唯一的方法是使用PS / CCI / Cecil并分析流程以拦截所有字段更新。 总之,不太可行。

可以说,唯一真正的方法是创建某种“观察者”组件,在一个单独的线程中运行,其作用是每隔一段时间读取一次属性,并在属性值发生变化时引发一个事件。 当然,这种解决方案在线程和同步的浑水中航行。

假设您的应用程序对于此对象是单线程的,那么最干净的解决方案是通过代理对象对此对象进行方法调用。 它的工作是检查属性的前后状态,并在事件发生变化时引发事件。

这是我正在谈论的一个简单例子:

 public class SomeProxy { public SomeProxy(ExternalObject obj) { _obj = obj; } public event EventArgs PropertyChanged; private bool _lastValue; private ExternalObject _obj; protected virtual void OnPropertyChanged() { if(PropertyChanged != null) PropertyChanged(); } protected virtual void PreMethodCall() { _lastValue = _obj.SomeProperty; } protected virtual void PostMethodCall() { if(_lastValue != _obj.SomeProperty) OnPropertyChanged(); } // Proxy method. public SomeMethod(int arg) { PreMethodCall(); _obj.SomeMethod(arg); // Call actual method. PostMethodCall(); } } 

显然,你可以将这个代理模式构建到一个合适的对象中 – 你只需要知道所有的调用都必须通过代理才能在你期望的时候引发事件。

如前所述,最直接的方法(以及需要对代码进行最少更改的方法)是使用诸如PostSharp之类的AOP库。

但是,使用传统的C#/ .NET可以通过使用依赖属性模式来实现解决方案,通过WPF使用效果非常好。 我建议阅读这个,并考虑为你的项目实现这样一个系统(或至少是它的简化版本),如果合适的话。

您需要在setter属性中创建一个包装类的类,在setter属性中使用常规方法在那里引发一个事件。

你可以从class级inheritance并隐藏财产吗? 这样的东西……

 class MyClass : BaseClass { // hide base property. public new bool MyProperty { get { return base.MyProperty; } set { base.MyProperty = value; RaiseMyPropertyChangedEvent(); } } } 

我认为Alex对包装器的想法很好,但是,鉴于对您来说最重要的是您知道在使用前更改了值,您可以简单地将通知移动到getter,避免内部值更改的后顾之忧。 这样你可以得到类似于轮询的东西,但是可靠:

 class MyClass : BaseClass { //local value private bool local; //first access yet? private bool accessed = false; // Override base property. public new bool MyProperty { get { if(!accessed) { // modify first-get case according to your taste, eg local = base.MyProperty; accessed = true; RaiseMyPropertyChangedBeforeUseEvent(); } else { if(local != base.MyProperty) { local = base.MyProperty; RaiseMyPropertyChangedBeforeUseEvent(); } } return local; } set { base.MyProperty = value; } } } 

您可以尝试inheritance它并使用它的孩子而不是它。 覆盖属性的“set”,以便引发事件。

编辑:…只有属性在父类中是虚拟的…