Code:
/ 4.0 / 4.0 / untmp / DEVDIV_TFS / Dev10 / Releases / RTMRel / wpf / src / UIAutomation / UIAutomationClient / System / Windows / Automation / CacheRequest.cs / 1305600 / CacheRequest.cs
//----------------------------------------------------------------------------
//
//
// Copyright (C) Microsoft Corporation. All rights reserved.
//
//
//
// Description: Class that describes the data to be pre-fected in Automation
// element operations, and manange the current request.
//
// History:
// 02/05/2004 : BrendanM Ported to WCP
//
//---------------------------------------------------------------------------
using System;
using System.Collections;
using System.Diagnostics;
using System.Windows.Automation;
using MS.Internal.Automation;
namespace System.Windows.Automation
{
///
/// Specified type of reference to use when returning AutomationElements
///
///
/// AutomationElementMode.Full is the default, and specified that returned AutomationElements
/// contain a full reference to the underlying UI.
///
/// AutomationElementMode.None specifies taht the returned AutomationElements have no
/// reference to the underlying UI, and contain only cached information.
///
/// Certain operations on AutomationElements, such as GetCurrentProperty
/// or SetFocus require a full reference; attempting to perform these on an
/// AutomationElement that has AutomationElementMode.None will result in an
/// InvalidOperationException being thrown.
///
/// Using AutomationElementMode.None can be more efficient when only properties are needed,
/// as it avoids the overhead involved in setting up full references.
///
#if (INTERNAL_COMPILE)
internal enum AutomationElementMode
#else
public enum AutomationElementMode
#endif
{
///
/// Specifies that returned AutomationElements have no reference to the
/// underlying UI, and contain only cached information.
///
None,
///
/// Specifies that returned AutomationElements have a full reference to the
/// underlying UI.
///
Full
}
// Implementation notes:
//
// CacheRequest is the user-facing class that is used to build up
// cache requests, using Add and the other properties. When activated,
// the data is gathered into a UiaCacheRequest instance, which is
// immutable - these are what the rest of UIA uses internally.
//
// The default cache request - which appears to be always at the bottom
// of the stack and which cannot be moved - is not actually part of the
// stack. Instead, current returns it whever the stack is empty.
///
/// Class used to specify the properties and patterns that should be
/// prefetched by UIAutomation when returning AutomationElements.
///
#if (INTERNAL_COMPILE)
internal sealed class CacheRequest
#else
public sealed class CacheRequest
#endif
{
//-----------------------------------------------------
//
// Constructors
//
//-----------------------------------------------------
#region Constructors
///
/// Create a new CacheRequest with default values.
///
///
/// A Thread's current CacheRequest determins which properties,
/// patterns and relative elements - if any - are pre-fetched by
/// AutomationElement.
///
/// A default cache request works on the Control view of the tree,
/// and does not prefetch any properties or patterns.
///
/// Use .Push or .Activate to make the CacheRequest the current active
/// CacheRequest for the current thread.
///
public CacheRequest()
{
_instanceLock = new object();
_viewCondition = Automation.ControlViewCondition;
_scope = TreeScope.Element;
_properties = new ArrayList();
_patterns = new ArrayList();
_automationElementMode = AutomationElementMode.Full;
// We always want RuntimeID to be available...
_properties.Add(AutomationElement.RuntimeIdProperty);
_uiaCacheRequest = DefaultUiaCacheRequest;
}
// Private ctor used by Clone()
private CacheRequest( Condition viewCondition,
TreeScope scope,
ArrayList properties,
ArrayList patterns,
AutomationElementMode automationElementMode,
UiaCoreApi.UiaCacheRequest uiaCacheRequest)
{
_instanceLock = new object();
_viewCondition = viewCondition;
_scope = scope;
_properties = properties;
_patterns = patterns;
_automationElementMode = automationElementMode;
_uiaCacheRequest = uiaCacheRequest;
}
#endregion Constructors
//------------------------------------------------------
//
// Public Methods
//
//-----------------------------------------------------
#region Public Methods
///
/// Push this CacheRequest onto this thread's stack of CacheRequests,
/// making it the current CacheRequest for this thread.
///
///
/// Use Pop to remove this CacheRequest from the stack, making the previously
/// active CacheRequest active again. CacheRequests can be pushed multiple times,
/// and on multiple threads; but for each thread, must be popped off in the
/// same order as they were pushed.
///
/// A CacheRequest cannot be modified while it is pushed on any thread; attempting
/// to modify it will generate an InvalidOperationException.
///
public void Push()
{
// pushing multiple times is legal,
// and pushing on different threads is also legal,
// so no preconditions to check for here.
AutomationProperty[] propertyArray = (AutomationProperty[])_properties.ToArray(typeof(AutomationProperty));
AutomationPattern[] patternArray = (AutomationPattern[])_patterns.ToArray(typeof(AutomationPattern));
// _threadStack is thread local storage (TLS) based, so can be
// accessed outside of the lock.
if (_threadStack == null)
{
_threadStack = new Stack();
}
_threadStack.Push(this);
lock (_instanceLock)
{
_refCount++;
// Generate a new UiaCacheRequest
if (_uiaCacheRequest == null)
{
_uiaCacheRequest = new UiaCoreApi.UiaCacheRequest(_viewCondition, _scope, propertyArray, patternArray, _automationElementMode);
}
}
}
///
/// Pop this CacheRequest from the current thread's stack of CacheRequests,
/// restoring the previously active CacheRequest.
///
///
/// Only the currently active CacheRequest can be popped, attempting to pop
/// a CacheRequest which is not the current one will result in an InvalidOperation
/// Exception.
///
/// The CacheRequest stack initially contains a default CacheRequest, which
/// cannot be popped off the stack.
///
public void Pop()
{
// ensure that this is top of stack
// (no lock needed here, since this is per-thread state)
if (_threadStack == null || _threadStack.Count == 0 || _threadStack.Peek() != this)
{
throw new InvalidOperationException(SR.Get(SRID.CacheReqestCanOnlyPopTop));
}
_threadStack.Pop();
lock (_instanceLock)
{
_refCount--;
}
}
///
/// Make this the currenly active CacheRequest.
///
///
/// Returns an IDisposable which should be disposed
/// when finished using this CacheRequest to deactivate it.
/// This method is designed for use within a 'using' clause.
///
public IDisposable Activate()
{
Push();
return new CacheRequestActivation(this);
}
///
/// Clone this CacheRequest
///
///
/// The returned CacheRequest contains the same request information, but is not
/// pushed on the state of any thread.
///
public CacheRequest Clone()
{
// New copy contains only temp state, not any locking state (_refCount)
return new CacheRequest(_viewCondition, _scope, (ArrayList)_properties.Clone(), (ArrayList)_patterns.Clone(), _automationElementMode, _uiaCacheRequest);
}
///
/// Add an AutomationProperty to this CacheRequest
///
/// The identifier of the property to add to this CacheRequest
public void Add(AutomationProperty property)
{
Misc.ValidateArgumentNonNull(property, "property");
lock (_instanceLock)
{
CheckAccess();
if (!_properties.Contains(property))
{
_properties.Add(property);
Invalidate();
}
}
}
///
/// Add an AutomationPattern to this CacheRequest
///
/// The identifier of the pattern to add to this CacheRequest
public void Add(AutomationPattern pattern)
{
Misc.ValidateArgumentNonNull(pattern, "pattern");
lock (_instanceLock)
{
CheckAccess();
if (!_patterns.Contains(pattern))
{
_patterns.Add(pattern);
Invalidate();
}
}
}
#endregion Public Methods
//------------------------------------------------------
//
// Public Properties
//
//------------------------------------------------------
#region Public Properties
///
/// Indicate which nodes should be pre-fetched
///
///
/// At least one or more of of TreeScope.Element, TreeScope.Children or
/// TreeScope.Descendants must be specified.
///
/// TreeScope.Parent and TreeScope.Ancestors are not supported.
///
public TreeScope TreeScope
{
get
{
return _scope;
}
set
{
if (value == 0)
{
throw new ArgumentException(SR.Get(SRID.TreeScopeNeedAtLeastOne));
}
if ((value & ~(TreeScope.Element | TreeScope.Children | TreeScope.Descendants)) != 0)
{
throw new ArgumentException(SR.Get(SRID.TreeScopeElementChildrenDescendantsOnly));
}
lock (_instanceLock)
{
CheckAccess();
if (_scope != value)
{
_scope = value;
Invalidate();
}
}
}
}
///
/// Indicates the view to use when prefetching relative nodes
///
/// Defaults to Automation.ControlViewCondition
public Condition TreeFilter
{
get
{
return _viewCondition;
}
set
{
Misc.ValidateArgumentNonNull(value, "TreeFilter");
lock (_instanceLock)
{
CheckAccess();
if (_viewCondition != value)
{
_viewCondition = value;
Invalidate();
}
}
}
}
///
/// Specifies whether returned AutomationElements should contain
/// full references to the underlying UI, or only cached information.
///
public AutomationElementMode AutomationElementMode
{
get
{
return _automationElementMode;
}
set
{
lock (_instanceLock)
{
CheckAccess();
if (_automationElementMode != value)
{
_automationElementMode = value;
Invalidate();
}
}
}
}
///
/// Return the most recent CacheRequest which has been activated
/// by teh calling thread.
///
public static CacheRequest Current
{
get
{
if ( _threadStack == null || _threadStack.Count == 0 )
return DefaultCacheRequest;
return (CacheRequest)_threadStack.Peek();
}
}
#endregion Public Properties
//-----------------------------------------------------
//
// Internal Properties
//
//------------------------------------------------------
#region Internal Properties
internal static UiaCoreApi.UiaCacheRequest DefaultUiaCacheRequest
{
get
{
if(_defaultUiaCacheRequest == null)
{
_defaultUiaCacheRequest = new UiaCoreApi.UiaCacheRequest(Automation.ControlViewCondition, TreeScope.Element, new AutomationProperty[] { AutomationElement.RuntimeIdProperty }, new AutomationPattern[] { }, AutomationElementMode.Full);
}
return _defaultUiaCacheRequest;
}
}
#endregion Internal Properties
//-----------------------------------------------------
//
// Internal Methods
//
//-----------------------------------------------------
#region Internal Methods
internal UiaCoreApi.UiaCacheRequest GetUiaCacheRequest()
{
if (_uiaCacheRequest == null)
{
AutomationProperty[] propertiesArray = (AutomationProperty[])_properties.ToArray(typeof(AutomationProperty));
AutomationPattern[] patternsArray = (AutomationPattern[])_patterns.ToArray(typeof(AutomationPattern));
lock (_instanceLock)
{
_uiaCacheRequest = new UiaCoreApi.UiaCacheRequest(_viewCondition, _scope, propertiesArray, patternsArray, _automationElementMode);
}
}
return _uiaCacheRequest;
}
static internal UiaCoreApi.UiaCacheRequest CurrentUiaCacheRequest
{
get
{
// No need to lock here, since this only uses thread state,
// and the UiaCacheRequests are generated within a lock in Push.
CacheRequest current = Current;
return current._uiaCacheRequest;
}
}
#endregion Internal Methods
//-----------------------------------------------------
//
// Private Methods
//
//------------------------------------------------------
#region Private Methods
// Ensure that this CacheRequest isn't currently in use
// Must be called within a lock(_instanceLock) to ensure
// thread consistency
void CheckAccess()
{
// Make sure this isn't being used by any thread's
// CacheRequest stacks by using a refcount:
// (Also check for defaultCacheRequest explicitly, since it
// is never explicitly added to the stack)
if (_refCount != 0 || this == DefaultCacheRequest)
{
throw new InvalidOperationException(SR.Get(SRID.CacheReqestCantModifyWhileActive));
}
}
// Called when state changes - sets _uiaCacheRequest to null
// to ensure that a clean one is generated next time Push is called
void Invalidate()
{
_uiaCacheRequest = null;
}
#endregion Private Methods
//-----------------------------------------------------
//
// Private Fields
//
//------------------------------------------------------
#region Private Fields
//--- Instance state ---
// Current mutable state...
Condition _viewCondition;
TreeScope _scope;
ArrayList _properties;
ArrayList _patterns;
AutomationElementMode _automationElementMode;
// When we Push, the current state is bundled into this, which is
// immutable. This is what the underlying requesting mechanism uses
UiaCoreApi.UiaCacheRequest _uiaCacheRequest;
// Used to track whether this instance is in use - inc'd on Push,
// dec'd on Pop...
int _refCount = 0;
// Used to lock on this instance...
object _instanceLock = null;
//--- Per-Thread state ---
// The stack of CacheRequests for this thread. Note that these need to be inited
// on-demand, as static initialization does not work with [ThreadStatic] members -
// it only applies to the first thread. Treat null as being the same as a stack with
// just DefaultCacheRequest on it.
[ThreadStatic]
private static Stack _threadStack;
//--- Global/Static state ---
internal static readonly CacheRequest DefaultCacheRequest = new CacheRequest();
internal static UiaCoreApi.UiaCacheRequest _defaultUiaCacheRequest;
#endregion Private Fields
}
//------------------------------------------------------
//
// Related utility classe
//
//-----------------------------------------------------
// Helper class returned by Access() - a using() block
// will call Dispose() on this when it goes out of scope.
internal class CacheRequestActivation : IDisposable
{
internal CacheRequestActivation(CacheRequest request)
{
_request = request;
}
public void Dispose()
{
Debug.Assert( _request != null );
if( _request != null )
{
_request.Pop();
_request = null;
}
}
// No finalizer - usually Dispose is used with a finalizer,
// but in this case, IDisposable is being used to manage scoping,
// not ensure that resources are freed.
private CacheRequest _request;
}
}
// File provided for Reference Use Only by Microsoft Corporation (c) 2007.
// Copyright (c) Microsoft Corporation. All rights reserved.
Link Menu

This book is available now!
Buy at Amazon US or
Buy at Amazon UK
- TemplateEditingFrame.cs
- ComponentCommands.cs
- HttpHeaderCollection.cs
- TemplateColumn.cs
- CalendarDay.cs
- RepeaterDesigner.cs
- DirectoryGroupQuery.cs
- HandleCollector.cs
- SaveFileDialog.cs
- LeaseManager.cs
- ComponentEditorPage.cs
- XPathExpr.cs
- MobileUserControlDesigner.cs
- XmlSchemaAnnotation.cs
- SqlDependency.cs
- RemoteWebConfigurationHostStream.cs
- EnterpriseServicesHelper.cs
- DelegateInArgument.cs
- ControlPropertyNameConverter.cs
- ProtectedProviderSettings.cs
- ScaleTransform.cs
- HtmlInputFile.cs
- Ray3DHitTestResult.cs
- ProtocolsSection.cs
- StoreContentChangedEventArgs.cs
- DeploymentExceptionMapper.cs
- SiteMapHierarchicalDataSourceView.cs
- FlowLayoutPanel.cs
- NamedPipeConnectionPoolSettingsElement.cs
- AffineTransform3D.cs
- UnmanagedHandle.cs
- DbFunctionCommandTree.cs
- DBConnectionString.cs
- COM2PropertyPageUITypeConverter.cs
- UriExt.cs
- TabControlCancelEvent.cs
- EditorPart.cs
- safex509handles.cs
- BufferedMessageWriter.cs
- TrustManagerMoreInformation.cs
- Compiler.cs
- CollectionsUtil.cs
- BadImageFormatException.cs
- DataControlField.cs
- XmlArrayAttribute.cs
- NameTable.cs
- ZoneMembershipCondition.cs
- Button.cs
- IssuedTokenServiceElement.cs
- SamlAction.cs
- SystemPens.cs
- CompilerError.cs
- ParserStreamGeometryContext.cs
- xamlnodes.cs
- CultureTableRecord.cs
- RegexCompiler.cs
- CompositionTarget.cs
- DefinitionBase.cs
- SqlConnectionPoolGroupProviderInfo.cs
- RegexCharClass.cs
- LambdaCompiler.Lambda.cs
- HttpContext.cs
- DoWorkEventArgs.cs
- ToolStripSplitStackLayout.cs
- BitmapData.cs
- StructuralType.cs
- Size3D.cs
- FullTextState.cs
- TemplatePagerField.cs
- DataServiceRequestOfT.cs
- TextServicesManager.cs
- recordstatescratchpad.cs
- Underline.cs
- FlatButtonAppearance.cs
- HuffmanTree.cs
- StaticSiteMapProvider.cs
- TreeView.cs
- ItemsControlAutomationPeer.cs
- CancelAsyncOperationRequest.cs
- Delay.cs
- GenericTypeParameterBuilder.cs
- WindowsAuthenticationEventArgs.cs
- XhtmlBasicCalendarAdapter.cs
- XmlSchemaRedefine.cs
- BitVector32.cs
- SqlDataSourceRefreshSchemaForm.cs
- ViewBox.cs
- SqlProviderManifest.cs
- DataGridCell.cs
- SpAudioStreamWrapper.cs
- DataGridItemEventArgs.cs
- FolderNameEditor.cs
- XamlWriter.cs
- NotConverter.cs
- FaultHandlingFilter.cs
- WindowsPrincipal.cs
- QuaternionAnimation.cs
- SQLMoneyStorage.cs
- DefaultProxySection.cs
- XmlCharacterData.cs