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
- TextEndOfSegment.cs
- NegotiateStream.cs
- FaultDescriptionCollection.cs
- XmlSchema.cs
- EncryptedType.cs
- HebrewCalendar.cs
- Task.cs
- XmlReader.cs
- SecurityState.cs
- ResourcesGenerator.cs
- Console.cs
- Cursors.cs
- LogicalMethodInfo.cs
- DependentList.cs
- listitem.cs
- BindingBase.cs
- EdgeProfileValidation.cs
- WorkflowViewService.cs
- XmlResolver.cs
- AncillaryOps.cs
- MenuItemCollection.cs
- ViewBox.cs
- PropertyFilterAttribute.cs
- AutomationTextAttribute.cs
- DoWorkEventArgs.cs
- ErrorWebPart.cs
- ChooseAction.cs
- DictationGrammar.cs
- XmlTextReaderImplHelpers.cs
- SoapHelper.cs
- SecurityPolicySection.cs
- DiscoveryExceptionDictionary.cs
- SelectionGlyph.cs
- Point3DKeyFrameCollection.cs
- SimpleRecyclingCache.cs
- SpotLight.cs
- MetaData.cs
- AssociatedControlConverter.cs
- XmlEncoding.cs
- _ConnectOverlappedAsyncResult.cs
- SortedList.cs
- XmlSchemaException.cs
- MinMaxParagraphWidth.cs
- WebPartHeaderCloseVerb.cs
- dbdatarecord.cs
- DictionaryContent.cs
- LinkConverter.cs
- Descriptor.cs
- DesignDataSource.cs
- TextTreeNode.cs
- MobileCategoryAttribute.cs
- ColorConvertedBitmap.cs
- RoleServiceManager.cs
- PlacementWorkspace.cs
- Roles.cs
- FocusManager.cs
- _ConnectionGroup.cs
- EntityClientCacheEntry.cs
- ContainsRowNumberChecker.cs
- Rijndael.cs
- PrinterUnitConvert.cs
- BaseValidator.cs
- ParamArrayAttribute.cs
- Thumb.cs
- TextBreakpoint.cs
- UnionCodeGroup.cs
- CodeAccessPermission.cs
- PolicyManager.cs
- EncryptedKeyIdentifierClause.cs
- HttpAsyncResult.cs
- cookiecollection.cs
- HashStream.cs
- Object.cs
- IssuanceLicense.cs
- DesignerDataConnection.cs
- GroupQuery.cs
- GestureRecognitionResult.cs
- FamilyCollection.cs
- MatchingStyle.cs
- DeferredSelectedIndexReference.cs
- StructuredTypeEmitter.cs
- wgx_render.cs
- TdsParserHelperClasses.cs
- TypeToken.cs
- SchemaObjectWriter.cs
- ProfileInfo.cs
- WindowsFormsSynchronizationContext.cs
- IdentityNotMappedException.cs
- ImageFormatConverter.cs
- FilterableAttribute.cs
- SmtpNegotiateAuthenticationModule.cs
- QueryOutputWriter.cs
- PropertyInfo.cs
- SqlCacheDependency.cs
- PackUriHelper.cs
- safex509handles.cs
- Label.cs
- MessagePropertyVariants.cs
- GlobalProxySelection.cs
- HierarchicalDataBoundControl.cs