Code:
/ 4.0 / 4.0 / 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. //---------------------------------------------------------------------------- // // // 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
- TypeViewSchema.cs
- FixedSOMLineCollection.cs
- serverconfig.cs
- BuiltInExpr.cs
- User.cs
- ClientScriptManager.cs
- GetWinFXPath.cs
- Visual3D.cs
- RotateTransform3D.cs
- QueryOutputWriter.cs
- EntryIndex.cs
- MemoryPressure.cs
- XsltLoader.cs
- PagesChangedEventArgs.cs
- MarginsConverter.cs
- DataColumnChangeEvent.cs
- rsa.cs
- FixedNode.cs
- MemberCollection.cs
- XmlSchemaAnnotated.cs
- TypeReference.cs
- HorizontalAlignConverter.cs
- HashHelper.cs
- FreeIndexList.cs
- IisTraceWebEventProvider.cs
- PresentationAppDomainManager.cs
- IndentTextWriter.cs
- UidPropertyAttribute.cs
- StateWorkerRequest.cs
- HostProtectionPermission.cs
- altserialization.cs
- HtmlEmptyTagControlBuilder.cs
- PerformanceCounterManager.cs
- QilLoop.cs
- RoutingEndpointTrait.cs
- CaseStatement.cs
- ParallelTimeline.cs
- CodeCompiler.cs
- SettingsPropertyValueCollection.cs
- FileRecordSequenceHelper.cs
- MenuItem.cs
- DataKey.cs
- PeerObject.cs
- CapabilitiesPattern.cs
- LinkLabel.cs
- XmlEntity.cs
- ThreadAbortException.cs
- XmlSignificantWhitespace.cs
- EnterpriseServicesHelper.cs
- XmlSerializer.cs
- CriticalHandle.cs
- TypeContext.cs
- CodeMemberProperty.cs
- OrCondition.cs
- NumberEdit.cs
- httpapplicationstate.cs
- UpdateException.cs
- PrimitiveXmlSerializers.cs
- LocatorPartList.cs
- EventHandlers.cs
- XmlDomTextWriter.cs
- IRCollection.cs
- PipeSecurity.cs
- SoapBinding.cs
- BatchParser.cs
- GeneralTransform3DTo2D.cs
- InputLanguageSource.cs
- AdvancedBindingEditor.cs
- BindingList.cs
- Pkcs7Signer.cs
- Matrix3DStack.cs
- RoleServiceManager.cs
- System.Data_BID.cs
- SafeFileMappingHandle.cs
- ClientTargetSection.cs
- Message.cs
- DataGridPageChangedEventArgs.cs
- CommandLineParser.cs
- BufferedGraphics.cs
- ToolstripProfessionalRenderer.cs
- RelationshipFixer.cs
- ITreeGenerator.cs
- HttpFileCollection.cs
- MetafileHeaderWmf.cs
- TypeContext.cs
- followingquery.cs
- ScrollProviderWrapper.cs
- ListViewGroupConverter.cs
- AnimationException.cs
- SessionEndedEventArgs.cs
- Label.cs
- StateInitialization.cs
- SQLDoubleStorage.cs
- HttpCookiesSection.cs
- Visual.cs
- DataServiceQueryException.cs
- WebConfigurationFileMap.cs
- SizeFConverter.cs
- ImageField.cs
- HostingPreferredMapPath.cs