| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216 |
- // Licensed to the .NET Foundation under one or more agreements.
- // The .NET Foundation licenses this file to you under the Apache 2.0 License.
- // See the LICENSE file in the project root for more information.
- #if WINDOWSPHONE7
- #if !DEBUG_NO_AGENT_SUPPORT
- //
- // The Windows Phone Marketplace Test Kit disallows usage of types
- // in the Microsoft.Phone.Shell namespace, determined by static code
- // analysis, for background agents.
- //
- // However, with a null check for PhoneApplicationService.Current,
- // we can safely use this the lifecycle events for dormant state
- // transitions. In a background agent this property will be null;
- // trying to create an instance of PhoneApplicationService throws
- // a ComException and is required to set the Current property.
- //
- // In order to access the PhoneApplicationService functionality for
- // non-background agent assemblies, we build a late bound wrapper
- // around the APIs.
- //
- // See appplat\src\Frameworks\Microsoft\Phone\PhoneApplicationService.cs
- // for implementation details of the class we use.
- //
- namespace System.Reactive.PlatformServices.Phone.Shell
- {
- using System;
- using System.Collections.Generic;
- using System.Linq.Expressions;
- using System.Reflection;
- using Microsoft.Phone;
- class PhoneApplicationService
- {
- private static readonly object s_gate = new object();
- internal static readonly Assembly s_phshAsm;
- private static readonly Type s_pasType;
- private static readonly PropertyInfo s_curProp;
- private static readonly EventInfo s_actdEvt;
- private static readonly EventInfo s_deacEvt;
- private readonly object _target;
- static PhoneApplicationService()
- {
- s_phshAsm = typeof(BackgroundAgent).Assembly; // Has to be in Microsoft.Phone.dll.
- s_pasType = s_phshAsm.GetType("Microsoft.Phone.Shell.PhoneApplicationService");
- s_curProp = s_pasType.GetProperty("Current", BindingFlags.Public | BindingFlags.Static);
- s_actdEvt = s_curProp.PropertyType.GetEvent("Activated", BindingFlags.Public | BindingFlags.Instance);
- s_deacEvt = s_curProp.PropertyType.GetEvent("Deactivated", BindingFlags.Public | BindingFlags.Instance);
- }
- private PhoneApplicationService(object target)
- {
- _target = target;
- }
- private static PhoneApplicationService s_current;
- public static PhoneApplicationService Current
- {
- get
- {
- lock (s_gate)
- {
- if (s_current == null)
- {
- var current = s_curProp.GetValue(null, null);
- if (current == null)
- return null;
- //
- // Current provides a singleton. The constructor
- // of PhoneApplicationService guarantees this,
- // throwing an InvalidOperationException if more
- // than one instance is created.
- //
- s_current = new PhoneApplicationService(current);
- }
- }
- return s_current;
- }
- }
- private Dictionary<object, object> _actdHandlers = new Dictionary<object, object>();
- public event EventHandler<ActivatedEventArgs> Activated
- {
- add
- {
- AddHandler<ActivatedEventArgs>(s_actdEvt, _actdHandlers, value);
- }
- remove
- {
- RemoveHandler(s_actdEvt, _actdHandlers, value);
- }
- }
- private Dictionary<object, object> _deacHandlers = new Dictionary<object, object>();
- public event EventHandler<DeactivatedEventArgs> Deactivated
- {
- add
- {
- AddHandler<DeactivatedEventArgs>(s_deacEvt, _deacHandlers, value);
- }
- remove
- {
- RemoveHandler(s_deacEvt, _deacHandlers, value);
- }
- }
- private void AddHandler<TEventArgs>(EventInfo evt, Dictionary<object, object> map, object handler)
- where TEventArgs : EventArgs
- {
- var h = GetHandler<TEventArgs>(evt, handler);
- var add = evt.GetAddMethod();
- lock (s_gate)
- {
- map.Add(handler, h);
- add.Invoke(_target, new object[] { h });
- }
- }
- private void RemoveHandler(EventInfo evt, Dictionary<object, object> map, object handler)
- {
- var rem = evt.GetRemoveMethod();
- lock (s_gate)
- {
- var h = default(object);
- if (map.TryGetValue(handler, out h))
- {
- //
- // We assume only one handler will be attached to
- // the event, hence we shouldn't worry about having
- // multiple delegate instances with the same target
- // being attached. This guarantee is made by the
- // reference counting in HostLifecycleService.
- //
- // The use of a dictionary allows for reuse with
- // multiple distinct handlers going forward.
- //
- map.Remove(handler);
- rem.Invoke(_target, new object[] { h });
- }
- }
- }
- private static object GetHandler<TEventArgsThunk>(EventInfo evt, object call)
- where TEventArgsThunk : EventArgs
- {
- var ht = evt.EventHandlerType;
- var hp = ht.GetMethod("Invoke").GetParameters();
- var po = Expression.Parameter(hp[0].ParameterType, hp[0].Name);
- var pe = Expression.Parameter(hp[1].ParameterType, hp[1].Name);
- var h = Expression.Lambda(
- ht,
- Expression.Invoke(
- Expression.Constant(call),
- po,
- Expression.New(
- typeof(TEventArgsThunk).GetConstructor(new[] { typeof(object) }),
- pe
- )
- ),
- po,
- pe
- );
- return h.Compile();
- }
- }
- class ActivatedEventArgs : EventArgs
- {
- private static readonly Type s_aeaType;
- private static readonly PropertyInfo s_aipProp;
- private readonly object _target;
- static ActivatedEventArgs()
- {
- s_aeaType = PhoneApplicationService.s_phshAsm.GetType("Microsoft.Phone.Shell.ActivatedEventArgs");
- s_aipProp = s_aeaType.GetProperty("IsApplicationInstancePreserved", BindingFlags.Public | BindingFlags.Instance);
- }
- public ActivatedEventArgs(object target)
- {
- _target = target;
- }
- public bool IsApplicationInstancePreserved
- {
- get
- {
- return (bool)s_aipProp.GetValue(_target, null);
- }
- }
- }
- class DeactivatedEventArgs : EventArgs
- {
- public DeactivatedEventArgs(object target)
- {
- }
- }
- }
- #endif
- #endif
|