2013-05-20 35 views
2

我爲我的Windows 8應用程序according to this guide實施行爲的修改版本。它的工作原理,除了一個地方,需要無功框架:如何在沒有Reactive框架的情況下將事件動態綁定到WinRT中的命令?

protected override void OnAttached() 
{ 
    var evt = AssociatedObject.GetType().GetRuntimeEvent(Event); 
    if (evt != null) 
    { 
    Observable.FromEventPattern<RoutedEventArgs>(AssociatedObject, Event) 
     .Subscribe(se => FireCommand()); 
    } 
    base.OnAttached(); 
} 

的問題很簡單,如何實現類似funcitonality沒有反應frmaework?我瀏覽了Rx的來源,可能是obtained here,但我對我來說太複雜了。
我也成功移植,唯一的問題代碼,它僅適用於固定式事件處理程序的工作:

protected override void OnAttached() 
{ 
    EventInfo evt = AssociatedObject.GetType().GetRuntimeEvent(Event); 
    if (evt != null) 
    { 
     AssignEvent<ItemClickEventHandler>(AssociatedObject, Event, FireCommand); 
    } 
    base.OnAttached(); 
} 

protected void AssignEvent<T1>(object instance, string eventName, T1 handler) 
{ 
    EventInfo runtimeEvent = instance.GetType().GetRuntimeEvent(eventName); 
    Func<T1, EventRegistrationToken> add = a => (EventRegistrationToken)runtimeEvent.AddMethod.Invoke(instance, new object[] { a }); 
    Action<EventRegistrationToken> remove = a => runtimeEvent.RemoveMethod.Invoke(runtimeEvent, new object[] { a }); 

    WindowsRuntimeMarshal.AddEventHandler(add, remove, handler); 
} 

任何想法,如何使它動態的,所以我沒有用具體的事件處理程序「ItemClickEventHandler」?注意在經典.NET這很簡單,但在WinRT中我不能使用Delegate.CreateDelegate(...)

更新: 由於布蘭登我能完成的方法,現在看起來像這樣:

protected override void OnAttached() 
{ 
    EventInfo evt = AssociatedObject.GetType().GetRuntimeEvent(Event); 
    if (evt != null) 
    { 
     MethodInfo addMethod = evt.AddMethod; 
     MethodInfo removeMethod = evt.RemoveMethod; 
     ParameterInfo[] addParameters = addMethod.GetParameters(); 
     Type delegateType = addParameters[0].ParameterType; 
     Action<object, object> handler = (s, e) => FireCommand(e as RoutedEventArgs); 
     MethodInfo handlerInvoke = typeof(Action<object, object>).GetRuntimeMethod("Invoke", new[] { typeof(object), typeof(object) }); 
     Delegate @delegate = handlerInvoke.CreateDelegate(delegateType, handler); 

     Func<object, EventRegistrationToken> add = a => (EventRegistrationToken)addMethod.Invoke(AssociatedObject, new object[] { @delegate }); 
     Action<EventRegistrationToken> remove = t => removeMethod.Invoke(AssociatedObject, new object[] { t }); 

     WindowsRuntimeMarshal.AddEventHandler(add, remove, handler); 
    } 
    base.OnAttached(); 
} 

現在我可以刪除800kB的Rx dll,再次感謝!

+0

刪除Rx代碼的任何特定原因?我認爲有一個核心的Rx庫甚至可以在RT上運行? – Brandon

+0

首先,我想將我的應用程序包的大小減少到一半,並且我想知道,它是如何在內部工作的。 –

+0

是否需要通過'WindowsRuntimeMarshal.AddEventHandler()'註冊事件處理程序?如果我們可以調用EventInfo對象的'Add'和'Remove'方法,解決這個問題並不難。 – Brandon

回答

2

我通過Rx源觸輪,這裏是功能最重要的一點:

MethodInfo addMethod = eventInfo.GetAddMethod(); 
MethodInfo removeMethod = eventInfo.GetRemoveMethod(); 
var addParameters = addMethod.GetParameters(); 
var delegateType = addParameters[0].ParameterType; 
Action<object, object> handler = (object sender, object eventArgs) => FireCommand(); 
MethodInfo handlerInvoke = typeof(Action<object, object>).GetMethod("Invoke"); 
Delegate delegate = handlerInvoke.CreateDelegate(delegateType, handler); 

Func<EventRegistrationToken> add = a => (EventRegistrationToken)addMethod.Invoke(instance, new object[] { delegate }); 
Action<EventRegistrationToken> remove = t => removeMethod.Invoke(instance, new object[] { t }); 

它看起來像重要的信息是,他們正在使用MethodInfo.CreateDelegate

+0

隨着一些WinRT的具體修改,我能夠使它工作,謝謝! –

相關問題