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
- VisualStyleRenderer.cs
- BinaryNode.cs
- Duration.cs
- CacheSection.cs
- DivideByZeroException.cs
- TdsParserHelperClasses.cs
- InputBinding.cs
- SqlUserDefinedTypeAttribute.cs
- SelectionProviderWrapper.cs
- SinglePageViewer.cs
- BypassElement.cs
- PixelShader.cs
- EventProviderClassic.cs
- EntityStoreSchemaGenerator.cs
- CompoundFileIOPermission.cs
- ScrollChrome.cs
- XmlSchemaAppInfo.cs
- RemotingSurrogateSelector.cs
- SafeHandles.cs
- Image.cs
- ObjectDataSourceFilteringEventArgs.cs
- HtmlInputReset.cs
- BookmarkEventArgs.cs
- Baml2006SchemaContext.cs
- PropertyMapper.cs
- AssemblyAttributes.cs
- IriParsingElement.cs
- HttpCapabilitiesSectionHandler.cs
- GetPageCompletedEventArgs.cs
- XamlUtilities.cs
- DataBindingExpressionBuilder.cs
- DataSourceIDConverter.cs
- TextTreeTextNode.cs
- Compiler.cs
- MasterPageBuildProvider.cs
- Tuple.cs
- IsolatedStorageFileStream.cs
- httpapplicationstate.cs
- SerializationInfo.cs
- Mouse.cs
- XPathException.cs
- Brush.cs
- ToolStripOverflowButton.cs
- FilteredXmlReader.cs
- StatusStrip.cs
- AnnotationDocumentPaginator.cs
- TranslateTransform3D.cs
- SwitchLevelAttribute.cs
- EndpointAddress.cs
- SortedList.cs
- RegexGroup.cs
- Attributes.cs
- EntryPointNotFoundException.cs
- DataGridTable.cs
- Section.cs
- CallTemplateAction.cs
- EncoderBestFitFallback.cs
- ControlCachePolicy.cs
- TemplatePropertyEntry.cs
- TypeBuilder.cs
- ColumnCollection.cs
- EmptyCollection.cs
- Label.cs
- SelectionChangedEventArgs.cs
- MsmqProcessProtocolHandler.cs
- TableRowGroupCollection.cs
- DataGridViewColumnCollection.cs
- ReachVisualSerializer.cs
- MetafileHeader.cs
- CommandExpr.cs
- ActivationServices.cs
- SRef.cs
- ItemsControlAutomationPeer.cs
- BindingMemberInfo.cs
- ClientConfigPaths.cs
- UnlockInstanceCommand.cs
- MapPathBasedVirtualPathProvider.cs
- DisplayInformation.cs
- ComponentChangedEvent.cs
- PathParser.cs
- CorePropertiesFilter.cs
- IPGlobalProperties.cs
- ToolStripLocationCancelEventArgs.cs
- HttpCachePolicyWrapper.cs
- CodeFieldReferenceExpression.cs
- Equal.cs
- GeometryModel3D.cs
- TypeCodeDomSerializer.cs
- CancelEventArgs.cs
- DataGridViewControlCollection.cs
- ResourceDictionary.cs
- TextModifier.cs
- Parameter.cs
- PeerApplication.cs
- DropAnimation.xaml.cs
- ChtmlTextWriter.cs
- TraceSection.cs
- EntityDataSourceViewSchema.cs
- COM2IDispatchConverter.cs
- GridToolTip.cs