Code:
/ 4.0 / 4.0 / untmp / DEVDIV_TFS / Dev10 / Releases / RTMRel / ndp / fx / src / Core / Microsoft / Scripting / Actions / DynamicMetaObjectBinder.cs / 1305376 / DynamicMetaObjectBinder.cs
/* **************************************************************************** * * Copyright (c) Microsoft Corporation. * * This source code is subject to terms and conditions of the Microsoft Public License. A * copy of the license can be found in the License.html file at the root of this distribution. If * you cannot locate the Microsoft Public License, please send an email to * dlr@microsoft.com. By using this source code in any fashion, you are agreeing to be bound * by the terms of the Microsoft Public License. * * You must not remove this notice, or any other, from this software. * * * ***************************************************************************/ using System.Collections.ObjectModel; using System.Diagnostics; using System.Dynamic.Utils; using System.Linq.Expressions; using System.Linq.Expressions.Compiler; using System.Runtime.CompilerServices; #if SILVERLIGHT using System.Core; #else using System.Runtime.Remoting; #endif namespace System.Dynamic { ////// The dynamic call site binder that participates in the ///binding protocol. /// /// The public abstract class DynamicMetaObjectBinder : CallSiteBinder { #region Public APIs ///performs the binding of the dynamic operation using the runtime values /// as input. On the other hand, the participates in the /// binding protocol. /// /// Initializes a new instance of the protected DynamicMetaObjectBinder() { } ///class. /// /// The result type of the operation. /// public virtual Type ReturnType { get { return typeof(object); } } ////// Performs the runtime binding of the dynamic operation on a set of arguments. /// /// An array of arguments to the dynamic operation. /// The array ofinstances that represent the parameters of the call site in the binding process. /// A LabelTarget used to return the result of the dynamic binding. /// /// An Expression that performs tests on the dynamic operation arguments, and /// performs the dynamic operation if hte tests are valid. If the tests fail on /// subsequent occurrences of the dynamic operation, Bind will be called again /// to produce a new public sealed override Expression Bind(object[] args, ReadOnlyCollectionfor the new argument types. /// parameters, LabelTarget returnLabel) { ContractUtils.RequiresNotNull(args, "args"); ContractUtils.RequiresNotNull(parameters, "parameters"); ContractUtils.RequiresNotNull(returnLabel, "returnLabel"); if (args.Length == 0) { throw Error.OutOfRange("args.Length", 1); } if (parameters.Count == 0) { throw Error.OutOfRange("parameters.Count", 1); } if (args.Length != parameters.Count) { throw new ArgumentOutOfRangeException("args"); } // Ensure that the binder's ReturnType matches CallSite's return // type. We do this so meta objects and language binders can // compose trees together without needing to insert converts. Type expectedResult; if (IsStandardBinder) { expectedResult = ReturnType; if (returnLabel.Type != typeof(void) && !TypeUtils.AreReferenceAssignable(returnLabel.Type, expectedResult)) { throw Error.BinderNotCompatibleWithCallSite(expectedResult, this, returnLabel.Type); } } else { // Even for non-standard binders, we have to at least make sure // it works with the CallSite's type to build the return. expectedResult = returnLabel.Type; } DynamicMetaObject target = DynamicMetaObject.Create(args[0], parameters[0]); DynamicMetaObject[] metaArgs = CreateArgumentMetaObjects(args, parameters); DynamicMetaObject binding = Bind(target, metaArgs); if (binding == null) { throw Error.BindingCannotBeNull(); } Expression body = binding.Expression; BindingRestrictions restrictions = binding.Restrictions; // Ensure the result matches the expected result type. if (expectedResult != typeof(void) && !TypeUtils.AreReferenceAssignable(expectedResult, body.Type)) { // // Blame the last person that handled the result: assume it's // the dynamic object (if any), otherwise blame the language. // if (target.Value is IDynamicMetaObjectProvider) { throw Error.DynamicObjectResultNotAssignable(body.Type, target.Value.GetType(), this, expectedResult); } else { throw Error.DynamicBinderResultNotAssignable(body.Type, this, expectedResult); } } // if the target is IDO, standard binders ask it to bind the rule so we may have a target-specific binding. // it makes sense to restrict on the target's type in such cases. // ideally IDO metaobjects should do this, but they often miss that type of "this" is significant. if (IsStandardBinder && args[0] as IDynamicMetaObjectProvider != null) { if (restrictions == BindingRestrictions.Empty) { throw Error.DynamicBindingNeedsRestrictions(target.Value.GetType(), this); } } restrictions = AddRemoteObjectRestrictions(restrictions, args, parameters); // Add the return if (body.NodeType != ExpressionType.Goto) { body = Expression.Return(returnLabel, body); } // Finally, add restrictions if (restrictions != BindingRestrictions.Empty) { body = Expression.IfThen(restrictions.ToExpression(), body); } return body; } private static DynamicMetaObject[] CreateArgumentMetaObjects(object[] args, ReadOnlyCollection parameters) { DynamicMetaObject[] mos; if (args.Length != 1) { mos = new DynamicMetaObject[args.Length - 1]; for (int i = 1; i < args.Length; i++) { mos[i - 1] = DynamicMetaObject.Create(args[i], parameters[i]); } } else { mos = DynamicMetaObject.EmptyMetaObjects; } return mos; } private static BindingRestrictions AddRemoteObjectRestrictions(BindingRestrictions restrictions, object[] args, ReadOnlyCollection parameters) { #if !SILVERLIGHT for (int i = 0; i < parameters.Count; i++) { var expr = parameters[i]; var value = args[i] as MarshalByRefObject; // special case for MBR objects. // when MBR objects are remoted they can have different conversion behavior // so bindings created for local and remote objects should not be mixed. if (value != null && !IsComObject(value)) { BindingRestrictions remotedRestriction; if (RemotingServices.IsObjectOutOfAppDomain(value)) { remotedRestriction = BindingRestrictions.GetExpressionRestriction( Expression.AndAlso( Expression.NotEqual(expr, Expression.Constant(null)), Expression.Call( typeof(RemotingServices).GetMethod("IsObjectOutOfAppDomain"), expr ) ) ); } else { remotedRestriction = BindingRestrictions.GetExpressionRestriction( Expression.AndAlso( Expression.NotEqual(expr, Expression.Constant(null)), Expression.Not( Expression.Call( typeof(RemotingServices).GetMethod("IsObjectOutOfAppDomain"), expr ) ) ) ); } restrictions = restrictions.Merge(remotedRestriction); } } #endif return restrictions; } /// /// When overridden in the derived class, performs the binding of the dynamic operation. /// /// The target of the dynamic operation. /// An array of arguments of the dynamic operation. ///The public abstract DynamicMetaObject Bind(DynamicMetaObject target, DynamicMetaObject[] args); ///representing the result of the binding. /// Gets an expression that will cause the binding to be updated. It /// indicates that the expression's binding is no longer valid. /// This is typically used when the "version" of a dynamic object has /// changed. /// /// TheType property of the resulting expression; any type is allowed. ///The update expression. [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1822:MarkMembersAsStatic")] public Expression GetUpdateExpression(Type type) { return Expression.Goto(CallSiteBinder.UpdateLabel, type); } ////// Defers the binding of the operation until later time when the runtime values of all dynamic operation arguments have been computed. /// /// The target of the dynamic operation. /// An array of arguments of the dynamic operation. ///The public DynamicMetaObject Defer(DynamicMetaObject target, params DynamicMetaObject[] args) { ContractUtils.RequiresNotNull(target, "target"); if (args == null) { return MakeDeferred(target.Restrictions, target); } else { return MakeDeferred( target.Restrictions.Merge(BindingRestrictions.Combine(args)), args.AddFirst(target) ); } } ///representing the result of the binding. /// Defers the binding of the operation until later time when the runtime values of all dynamic operation arguments have been computed. /// /// An array of arguments of the dynamic operation. ///The public DynamicMetaObject Defer(params DynamicMetaObject[] args) { return MakeDeferred(BindingRestrictions.Combine(args), args); } private DynamicMetaObject MakeDeferred(BindingRestrictions rs, params DynamicMetaObject[] args) { var exprs = DynamicMetaObject.GetExpressions(args); Type delegateType = DelegateHelpers.MakeDeferredSiteDelegate(args, ReturnType); // Because we know the arguments match the delegate type (we just created the argument types) // we go directly to DynamicExpression.Make to avoid a bunch of unnecessary argument validation return new DynamicMetaObject( DynamicExpression.Make(ReturnType, delegateType, this, new TrueReadOnlyCollectionrepresenting the result of the binding. (exprs)), rs ); } #endregion // used to detect standard MetaObjectBinders. internal virtual bool IsStandardBinder { get { return false; } } #if !SILVERLIGHT private static readonly Type ComObjectType = typeof(object).Assembly.GetType("System.__ComObject"); private static bool IsComObject(object obj) { // we can't use System.Runtime.InteropServices.Marshal.IsComObject(obj) since it doesn't work in partial trust return obj != null && ComObjectType.IsAssignableFrom(obj.GetType()); } #endif } } // 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
- EventLogPermissionEntryCollection.cs
- ConfigXmlText.cs
- ReadOnlyMetadataCollection.cs
- RepeaterItemCollection.cs
- ValueQuery.cs
- LinkTarget.cs
- Operators.cs
- ColumnWidthChangingEvent.cs
- TraversalRequest.cs
- ResourcesChangeInfo.cs
- BuildManager.cs
- fixedPageContentExtractor.cs
- SqlInfoMessageEvent.cs
- Sorting.cs
- DataBindingExpressionBuilder.cs
- SynchronizationLockException.cs
- PointKeyFrameCollection.cs
- SystemIcmpV4Statistics.cs
- ZipFileInfo.cs
- InvalidEnumArgumentException.cs
- BlurBitmapEffect.cs
- QuaternionValueSerializer.cs
- Composition.cs
- SQLByteStorage.cs
- CreateUserErrorEventArgs.cs
- NamedPermissionSet.cs
- externdll.cs
- BoundPropertyEntry.cs
- Win32Exception.cs
- ObservableDictionary.cs
- XmlWrappingWriter.cs
- GridViewAutomationPeer.cs
- PackageRelationshipCollection.cs
- DataPointer.cs
- ItemType.cs
- TextEditorTables.cs
- SerializerWriterEventHandlers.cs
- StateWorkerRequest.cs
- BufferAllocator.cs
- ScriptingRoleServiceSection.cs
- IgnoreDeviceFilterElement.cs
- Char.cs
- DataGridRowClipboardEventArgs.cs
- DocumentPageHost.cs
- AndAlso.cs
- WebColorConverter.cs
- ButtonColumn.cs
- DoubleIndependentAnimationStorage.cs
- Thickness.cs
- DeclarativeCatalogPart.cs
- TextStore.cs
- FilterEventArgs.cs
- RankException.cs
- WebPartExportVerb.cs
- ColumnHeader.cs
- StateWorkerRequest.cs
- SocketPermission.cs
- CommentEmitter.cs
- DefaultCommandExtensionCallback.cs
- CornerRadius.cs
- EntityContainer.cs
- FacetDescription.cs
- SafeRightsManagementSessionHandle.cs
- Error.cs
- TransformProviderWrapper.cs
- OleDbFactory.cs
- TraversalRequest.cs
- WebResourceAttribute.cs
- Int64Converter.cs
- ConfigurationException.cs
- SpecialNameAttribute.cs
- HtmlElement.cs
- DBDataPermissionAttribute.cs
- ProfileServiceManager.cs
- DelayedRegex.cs
- WaitForChangedResult.cs
- CacheChildrenQuery.cs
- PathFigure.cs
- Typography.cs
- bindurihelper.cs
- RuntimeIdentifierPropertyAttribute.cs
- PersistenceIOParticipant.cs
- NavigatingCancelEventArgs.cs
- StreamUpdate.cs
- ConstructorArgumentAttribute.cs
- AppDomain.cs
- TreeView.cs
- XmlSchemaAny.cs
- LiteralControl.cs
- PeerPresenceInfo.cs
- Style.cs
- ProfileGroupSettings.cs
- Source.cs
- WriteFileContext.cs
- DataTableExtensions.cs
- CorrelationToken.cs
- RegexWorker.cs
- RowUpdatingEventArgs.cs
- SqlUserDefinedTypeAttribute.cs
- DataGridRelationshipRow.cs