Code:
/ 4.0 / 4.0 / untmp / DEVDIV_TFS / Dev10 / Releases / RTMRel / wpf / src / Framework / MS / Internal / Data / DynamicObjectAccessor.cs / 1305600 / DynamicObjectAccessor.cs
//---------------------------------------------------------------------------- // //// Copyright (C) Microsoft Corporation. All rights reserved. // // // Description: Accessors for dynamic objects // //--------------------------------------------------------------------------- using System; using System.Diagnostics; using System.Dynamic; // GetMemberBinder, etc. using System.Reflection; // PropertyInfo, etc. using System.Runtime.CompilerServices; // CallSite using System.Linq.Expressions; // Expression using SW = System.Windows; // SRID, SR namespace MS.Internal.Data { #region DynamicObjectAccessor internal class DynamicObjectAccessor { public DynamicObjectAccessor(Type ownerType, string propertyName) { _ownerType = ownerType; _propertyName = propertyName; } public Type OwnerType { get { return _ownerType; } } public string PropertyName { get { return _propertyName; } } public bool IsReadOnly { get { return false; } } public Type PropertyType { get { return typeof(object); } } Type _ownerType; string _propertyName; } #endregion DynamicObjectAccessor #region DynamicPropertyAccessor internal class DynamicPropertyAccessor : DynamicObjectAccessor { public DynamicPropertyAccessor(Type ownerType, string propertyName) : base(ownerType, propertyName) { } public object GetValue(object component) { if (_getter == null) { var binder = new TrivialGetMemberBinder(PropertyName); _getter = CallSite>.Create(binder); } return _getter.Target(_getter, component); } public void SetValue(object component, object value) { if (_setter == null) { var binder = new TrivialSetMemberBinder(PropertyName); _setter = CallSite >.Create(binder); } _setter.Target(_setter, component, value); } CallSite > _getter; CallSite > _setter; } #endregion DynamicPropertyAccessor #region DynamicIndexerAccessor internal class DynamicIndexerAccessor : DynamicObjectAccessor { private DynamicIndexerAccessor(int rank) : base(typeof(IDynamicMetaObjectProvider), "Items") { var getBinder = new TrivialGetIndexBinder(rank); var setBinder = new TrivialSetIndexBinder(rank); Type delegateType, callsiteType; MethodInfo createMethod; FieldInfo targetField; Type[] typeArgs; int i; // getter delegate type: Func typeArgs = new Type[rank+3]; typeArgs[0] = typeof(CallSite); for (i=1; i<=rank+2; ++i) { typeArgs[i] = typeof(object); } delegateType = Expression.GetDelegateType(typeArgs); // getter CallSite: CallSite >.Create(getBinder) callsiteType = typeof(CallSite<>).MakeGenericType(new Type[]{ delegateType }); createMethod = callsiteType.GetMethod("Create", new Type[]{ typeof(CallSiteBinder) }); _getterCallSite = (CallSite)createMethod.Invoke(null, new object[]{ getBinder }); // getter delegate: _getterCallSite.Target targetField = callsiteType.GetField("Target"); _getterDelegate = (MulticastDelegate)targetField.GetValue(_getterCallSite); // setter delegate type: Action typeArgs = new Type[rank+4]; typeArgs[0] = typeof(CallSite); typeArgs[rank+3] = typeof(void); for (i=1; i<=rank+2; ++i) { typeArgs[i] = typeof(object); } delegateType = Expression.GetDelegateType(typeArgs); // setter CallSite: CallSite >.Create(setBinder) callsiteType = typeof(CallSite<>).MakeGenericType(new Type[]{ delegateType }); createMethod = callsiteType.GetMethod("Create", new Type[]{ typeof(CallSiteBinder) }); _setterCallSite = (CallSite)createMethod.Invoke(null, new object[]{ setBinder }); // setter delegate: _setterCallSite.Target targetField = callsiteType.GetField("Target"); _setterDelegate = (MulticastDelegate)targetField.GetValue(_setterCallSite); } public object GetValue(object component, object[] args) { int rank = args.Length; object[] delegateArgs = new object[rank + 2]; delegateArgs[0] = _getterCallSite; delegateArgs[1] = component; Array.Copy(args, 0, delegateArgs, 2, rank); return _getterDelegate.DynamicInvoke(delegateArgs); } public void SetValue(object component, object[] args, object value) { int rank = args.Length; object[] delegateArgs = new object[rank + 3]; delegateArgs[0] = _setterCallSite; delegateArgs[1] = component; Array.Copy(args, 0, delegateArgs, 2, rank); delegateArgs[rank + 2] = value; _setterDelegate.DynamicInvoke(delegateArgs); } // ensure only one accessor for each rank public static DynamicIndexerAccessor GetIndexerAccessor(int rank) { if (_accessors.Length < rank || _accessors[rank-1] == null) { lock(_lock) { if (_accessors.Length < rank) { DynamicIndexerAccessor[] newAccessors = new DynamicIndexerAccessor[rank]; Array.Copy(_accessors, 0, newAccessors, 0, _accessors.Length); _accessors = newAccessors; } if (_accessors[rank-1] == null) { _accessors[rank-1] = new DynamicIndexerAccessor(rank); } } } return _accessors[rank-1]; } CallSite _getterCallSite, _setterCallSite; MulticastDelegate _getterDelegate, _setterDelegate; static DynamicIndexerAccessor[] _accessors = new DynamicIndexerAccessor[1]; static object _lock = new object(); } #endregion DynamicIndexerAccessor #region Trivial binders internal class TrivialGetMemberBinder : GetMemberBinder { public TrivialGetMemberBinder(string propertyName) : base(propertyName, false /*ignoreCase*/) { } public override DynamicMetaObject FallbackGetMember(DynamicMetaObject target, DynamicMetaObject errorSuggestion) { return errorSuggestion ?? TrivialBinderHelper.ThrowExpression(SW.SR.Get(SW.SRID.PropertyPathNoProperty, target, Name), ReturnType); } } internal class TrivialSetMemberBinder : SetMemberBinder { public TrivialSetMemberBinder(string propertyName) : base(propertyName, false /*ignoreCase*/) { } public override DynamicMetaObject FallbackSetMember(DynamicMetaObject target, DynamicMetaObject value, DynamicMetaObject errorSuggestion) { return errorSuggestion ?? TrivialBinderHelper.ThrowExpression(SW.SR.Get(SW.SRID.PropertyPathNoProperty, target, Name), ReturnType); } } internal class TrivialGetIndexBinder : GetIndexBinder { public TrivialGetIndexBinder(int rank) : base(new CallInfo(rank)) { } public override DynamicMetaObject FallbackGetIndex(DynamicMetaObject target, DynamicMetaObject[] indexes, DynamicMetaObject errorSuggestion) { return errorSuggestion ?? TrivialBinderHelper.ThrowExpression(SW.SR.Get(SW.SRID.PropertyPathNoProperty, target, "Items"), ReturnType); } } internal class TrivialSetIndexBinder : SetIndexBinder { public TrivialSetIndexBinder(int rank) : base(new CallInfo(rank)) { } public override DynamicMetaObject FallbackSetIndex(DynamicMetaObject target, DynamicMetaObject[] indexes, DynamicMetaObject value, DynamicMetaObject errorSuggestion) { return errorSuggestion ?? TrivialBinderHelper.ThrowExpression(SW.SR.Get(SW.SRID.PropertyPathNoProperty, target, "Items"), ReturnType); } } internal static class TrivialBinderHelper { public static DynamicMetaObject ThrowExpression(string message, Type returnType) { return new DynamicMetaObject( Expression.Throw( Expression.New( typeof(InvalidOperationException).GetConstructor(new Type[] { typeof(string) }), Expression.Constant(message) ), returnType ), BindingRestrictions.Empty ); } } #endregion Trivial binders } // 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
- MessagePartProtectionMode.cs
- UriTemplatePathSegment.cs
- TransformedBitmap.cs
- HTMLTagNameToTypeMapper.cs
- ReferenceService.cs
- EventProvider.cs
- HostSecurityManager.cs
- GridViewColumn.cs
- xsdvalidator.cs
- PictureBox.cs
- MouseGestureValueSerializer.cs
- PenContext.cs
- ColorAnimation.cs
- ObjectStateEntryDbUpdatableDataRecord.cs
- XmlSchemaSimpleContent.cs
- SqlClientPermission.cs
- QilTernary.cs
- ItemTypeToolStripMenuItem.cs
- ProtocolViolationException.cs
- XPathChildIterator.cs
- Util.cs
- EndpointDiscoveryElement.cs
- FontStyleConverter.cs
- StorageRoot.cs
- XmlValueConverter.cs
- PropertyEmitterBase.cs
- FormsAuthenticationUser.cs
- CompilerTypeWithParams.cs
- ZipIOFileItemStream.cs
- DBCSCodePageEncoding.cs
- ClientSideQueueItem.cs
- ImageInfo.cs
- TextFormatter.cs
- RadioButtonList.cs
- RegisteredExpandoAttribute.cs
- CaseExpr.cs
- BufferedWebEventProvider.cs
- TdsEnums.cs
- Common.cs
- arc.cs
- ColorMap.cs
- FastEncoder.cs
- ManagementEventArgs.cs
- GlyphRun.cs
- TCEAdapterGenerator.cs
- CommunicationException.cs
- SqlTransaction.cs
- GradientSpreadMethodValidation.cs
- SqlDataSourceConfigureSortForm.cs
- DesignerVerbCollection.cs
- RemotingAttributes.cs
- FixedPosition.cs
- newitemfactory.cs
- HandlerBase.cs
- ButtonBase.cs
- WebControlsSection.cs
- FormattedText.cs
- UnescapedXmlDiagnosticData.cs
- XmlUTF8TextReader.cs
- PackWebRequestFactory.cs
- TransformerTypeCollection.cs
- UIPermission.cs
- FacetDescriptionElement.cs
- RuntimeArgument.cs
- PropertyPath.cs
- RowUpdatingEventArgs.cs
- HTMLTagNameToTypeMapper.cs
- DefaultAsyncDataDispatcher.cs
- HtmlInputButton.cs
- Win32SafeHandles.cs
- SmiContext.cs
- XmlMemberMapping.cs
- SequentialOutput.cs
- SystemIPGlobalProperties.cs
- RotateTransform.cs
- RouteCollection.cs
- StagingAreaInputItem.cs
- Internal.cs
- DesignerForm.cs
- RequestCachingSection.cs
- brushes.cs
- TableItemPatternIdentifiers.cs
- SqlNotificationEventArgs.cs
- UserPreferenceChangedEventArgs.cs
- FormViewUpdatedEventArgs.cs
- SerializationIncompleteException.cs
- Model3DCollection.cs
- AccessDataSourceView.cs
- EntityType.cs
- AssemblyResourceLoader.cs
- SecUtil.cs
- AnnotationService.cs
- BaseComponentEditor.cs
- SolidBrush.cs
- ToolStripTextBox.cs
- TreeViewEvent.cs
- RuntimeCompatibilityAttribute.cs
- EntityDataSourceContextCreatedEventArgs.cs
- Wildcard.cs
- XmlEncodedRawTextWriter.cs