c#中的绑定/解绑定
本文关键字:绑定 | 更新日期: 2023-09-27 18:08:04
如何实现类似于jQuery的绑定/解绑定?
class MyDataType<T>
{
private List<T> data;
...
public void Add(T value)
{
data.Add(value);
}
...
}
...
MyDataTypeObject.Bind("Add",()=>Console.WriteLine("OnAdd"));
...
MyDataTypeObject.UnBind("Add");
...
您可以使用Castle DynamicProxy完成此操作。首先,创建包含Bind()
和Unbind()
方法的抽象基类,以及保存调用的字典:
public abstract class BindableBase
{
private readonly Dictionary<string, Action> m_boundMethods =
new Dictionary<string, Action>();
protected Dictionary<string, Action> BoundMethods
{
get { return m_boundMethods; }
}
public void Bind(string method, Action action)
{
if (!m_boundMethods.ContainsKey(method))
m_boundMethods.Add(method, null);
m_boundMethods[method] += action;
}
public void Unbind(string method, Action action)
{
if (m_boundMethods.ContainsKey(method))
{
m_boundMethods[method] -= action;
if (m_boundMethods[method] == null)
m_boundMethods.Remove(method);
}
}
}
然后创建实现BindableBase
的具体类。您需要将任何想要拦截的方法设置为virtual:
public class Foo<T> : BindableBase
{
private readonly List<T> m_data = new List<T>();
public virtual void Add(T value)
{
m_data.Add(value);
}
}
然后创建拦截器,拦截对任何虚方法的调用,并从字典中调用适当的委托:
class Interceptor : IInterceptor
{
private static readonly PropertyInfo BoundMethodsProperty =
typeof(BindableBase).GetProperty(
"BoundMethods", BindingFlags.Instance | BindingFlags.NonPublic);
public void Intercept(IInvocation invocation)
{
var boudMethods =
(Dictionary<string, Action>)BoundMethodsProperty.GetValue(
invocation.InvocationTarget, null);
invocation.Proceed();
string method = invocation.Method.Name;
Action action;
if (boudMethods.TryGetValue(method, out action))
action();
}
}
最后,这只是一个生成代理并使用它的问题:
var proxyGenerator = new ProxyGenerator();
Foo<int> foo = proxyGenerator.CreateClassProxy<Foo<int>>(new Interceptor());
foo.Bind("Add", LogAdd);
foo.Add(42);
foo.Unbind("Add", LogAdd);
foo.Add(43);
您可以模拟它,但只能使用Events的预定义方法。
class MyDataType<T>
{
EventHandler<EventArgs> OnAdded;
private RaiseOnAdded()
{
var onAdded = OnAdded
if(onAdded != null)
{
onAdded(this, new EventArgs());
}
}
private List<T> data;
...
public void Add(T value)
{
data.Add(value);
RaiseOnAdded(); // <-- Add knows to call OnAdded(..)
}
...
}
var hander = (s, e)=>Console.WriteLine("OnAdd"));
MyDataTypeObject.OnAdded += handler;
MyDataTypeObject.OnAdded -= handler;