Code:
/ 4.0 / 4.0 / DEVDIV_TFS / Dev10 / Releases / RTMRel / ndp / fx / src / Core / Microsoft / Scripting / Actions / CallSiteBinder.cs / 1305376 / CallSiteBinder.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.Generic; using System.Collections.ObjectModel; using System.Diagnostics; using System.Dynamic; using System.Dynamic.Utils; using System.Linq.Expressions; using System.Threading; using System.Reflection; #if SILVERLIGHT using System.Core; #endif //SILVERLIGHT namespace System.Runtime.CompilerServices { ////// Class responsible for runtime binding of the dynamic operations on the dynamic call site. /// public abstract class CallSiteBinder { private static readonly LabelTarget _updateLabel = Expression.Label("CallSiteBinder.UpdateLabel"); ////// The Level 2 cache - all rules produced for the same binder. /// internal DictionaryCache; /// /// Initializes a new instance of the protected CallSiteBinder() { } ///class. /// /// Gets a label that can be used to 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. /// public static LabelTarget UpdateLabel { get { return _updateLabel; } } private sealed class LambdaSignaturewhere T : class { internal static readonly LambdaSignature Instance = new LambdaSignature (); internal readonly ReadOnlyCollection Parameters; internal readonly LabelTarget ReturnLabel; private LambdaSignature() { Type target = typeof(T); if (!typeof(Delegate).IsAssignableFrom(target)) { throw Error.TypeParameterIsNotDelegate(target); } MethodInfo invoke = target.GetMethod("Invoke"); ParameterInfo[] pis = invoke.GetParametersCached(); if (pis[0].ParameterType != typeof(CallSite)) { throw Error.FirstArgumentMustBeCallSite(); } var @params = new ParameterExpression[pis.Length - 1]; for (int i = 0; i < @params.Length; i++) { @params[i] = Expression.Parameter(pis[i + 1].ParameterType, "$arg" + i); } Parameters = new TrueReadOnlyCollection (@params); ReturnLabel = Expression.Label(invoke.GetReturnType()); } } /// /// 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 abstract Expression Bind(object[] args, ReadOnlyCollectionfor the new argument types. /// parameters, LabelTarget returnLabel); /// /// Provides low-level runtime binding support. Classes can override this and provide a direct /// delegate for the implementation of rule. This can enable saving rules to disk, having /// specialized rules available at runtime, or providing a different caching policy. /// ///The target type of the CallSite. /// The CallSite the bind is being performed for. /// The arguments for the binder. ///A new delegate which replaces the CallSite Target. public virtual T BindDelegate(CallSite site, object[] args) where T : class { return null; } internal T BindCore (CallSite site, object[] args) where T : class { // // Try to find a precompiled delegate, and return it if found. // T result = BindDelegate(site, args); if (result != null) { return result; } // // Get the Expression for the binding // var signature = LambdaSignature .Instance; Expression binding = Bind(args, signature.Parameters, signature.ReturnLabel); // // Check the produced rule // if (binding == null) { throw Error.NoOrInvalidRuleProduced(); } // // finally produce the new rule if we need to // #if !MICROSOFT_SCRIPTING_CORE && !SILVERLIGHT // We cannot compile rules in the heterogeneous app domains since they // may come from less trusted sources // Silverlight always uses a homogenous appdomain, so we don’t need this check if (!AppDomain.CurrentDomain.IsHomogenous) { throw Error.HomogenousAppDomainRequired(); } #endif Expression e = Stitch(binding, signature); T newRule = e.Compile(); CacheTarget(newRule); return newRule; } /// /// Adds a target to the cache of known targets. The cached targets will /// be scanned before calling BindDelegate to produce the new rule. /// ///The type of target being added. /// The target delegate to be added to the cache. protected void CacheTarget(T target) where T : class { GetRuleCache ().AddRule(target); } private static Expression Stitch (Expression binding, LambdaSignature signature) where T : class { Type targetType = typeof(T); Type siteType = typeof(CallSite ); var body = new ReadOnlyCollectionBuilder (3); body.Add(binding); var site = Expression.Parameter(typeof(CallSite), "$site"); var @params = signature.Parameters.AddFirst(site); Expression updLabel = Expression.Label(CallSiteBinder.UpdateLabel); #if DEBUG // put the AST into the constant pool for debugging purposes updLabel = Expression.Block( Expression.Constant(binding, typeof(Expression)), updLabel ); #endif body.Add(updLabel); body.Add( Expression.Label( signature.ReturnLabel, Expression.Condition( Expression.Call( typeof(CallSiteOps).GetMethod("SetNotMatched"), @params.First() ), Expression.Default(signature.ReturnLabel.Type), Expression.Invoke( Expression.Property( Expression.Convert(site, siteType), typeof(CallSite ).GetProperty("Update") ), new TrueReadOnlyCollection (@params) ) ) ) ); return new Expression ( Expression.Block(body), "CallSite.Target", true, // always compile the rules with tail call optimization new TrueReadOnlyCollection (@params) ); } internal RuleCache GetRuleCache () where T : class { // make sure we have cache. if (Cache == null) { Interlocked.CompareExchange(ref Cache, new Dictionary (), null); } object ruleCache; var cache = Cache; lock (cache) { if (!cache.TryGetValue(typeof(T), out ruleCache)) { cache[typeof(T)] = ruleCache = new RuleCache (); } } RuleCache result = ruleCache as RuleCache ; Debug.Assert(result != null); return result; } } } // File provided for Reference Use Only by Microsoft Corporation (c) 2007. // Copyright (c) Microsoft Corporation. All rights reserved. /* **************************************************************************** * * 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.Generic; using System.Collections.ObjectModel; using System.Diagnostics; using System.Dynamic; using System.Dynamic.Utils; using System.Linq.Expressions; using System.Threading; using System.Reflection; #if SILVERLIGHT using System.Core; #endif //SILVERLIGHT namespace System.Runtime.CompilerServices { /// /// Class responsible for runtime binding of the dynamic operations on the dynamic call site. /// public abstract class CallSiteBinder { private static readonly LabelTarget _updateLabel = Expression.Label("CallSiteBinder.UpdateLabel"); ////// The Level 2 cache - all rules produced for the same binder. /// internal DictionaryCache; /// /// Initializes a new instance of the protected CallSiteBinder() { } ///class. /// /// Gets a label that can be used to 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. /// public static LabelTarget UpdateLabel { get { return _updateLabel; } } private sealed class LambdaSignaturewhere T : class { internal static readonly LambdaSignature Instance = new LambdaSignature (); internal readonly ReadOnlyCollection Parameters; internal readonly LabelTarget ReturnLabel; private LambdaSignature() { Type target = typeof(T); if (!typeof(Delegate).IsAssignableFrom(target)) { throw Error.TypeParameterIsNotDelegate(target); } MethodInfo invoke = target.GetMethod("Invoke"); ParameterInfo[] pis = invoke.GetParametersCached(); if (pis[0].ParameterType != typeof(CallSite)) { throw Error.FirstArgumentMustBeCallSite(); } var @params = new ParameterExpression[pis.Length - 1]; for (int i = 0; i < @params.Length; i++) { @params[i] = Expression.Parameter(pis[i + 1].ParameterType, "$arg" + i); } Parameters = new TrueReadOnlyCollection (@params); ReturnLabel = Expression.Label(invoke.GetReturnType()); } } /// /// 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 abstract Expression Bind(object[] args, ReadOnlyCollectionfor the new argument types. /// parameters, LabelTarget returnLabel); /// /// Provides low-level runtime binding support. Classes can override this and provide a direct /// delegate for the implementation of rule. This can enable saving rules to disk, having /// specialized rules available at runtime, or providing a different caching policy. /// ///The target type of the CallSite. /// The CallSite the bind is being performed for. /// The arguments for the binder. ///A new delegate which replaces the CallSite Target. public virtual T BindDelegate(CallSite site, object[] args) where T : class { return null; } internal T BindCore (CallSite site, object[] args) where T : class { // // Try to find a precompiled delegate, and return it if found. // T result = BindDelegate(site, args); if (result != null) { return result; } // // Get the Expression for the binding // var signature = LambdaSignature .Instance; Expression binding = Bind(args, signature.Parameters, signature.ReturnLabel); // // Check the produced rule // if (binding == null) { throw Error.NoOrInvalidRuleProduced(); } // // finally produce the new rule if we need to // #if !MICROSOFT_SCRIPTING_CORE && !SILVERLIGHT // We cannot compile rules in the heterogeneous app domains since they // may come from less trusted sources // Silverlight always uses a homogenous appdomain, so we don’t need this check if (!AppDomain.CurrentDomain.IsHomogenous) { throw Error.HomogenousAppDomainRequired(); } #endif Expression e = Stitch(binding, signature); T newRule = e.Compile(); CacheTarget(newRule); return newRule; } /// /// Adds a target to the cache of known targets. The cached targets will /// be scanned before calling BindDelegate to produce the new rule. /// ///The type of target being added. /// The target delegate to be added to the cache. protected void CacheTarget(T target) where T : class { GetRuleCache ().AddRule(target); } private static Expression Stitch (Expression binding, LambdaSignature signature) where T : class { Type targetType = typeof(T); Type siteType = typeof(CallSite ); var body = new ReadOnlyCollectionBuilder (3); body.Add(binding); var site = Expression.Parameter(typeof(CallSite), "$site"); var @params = signature.Parameters.AddFirst(site); Expression updLabel = Expression.Label(CallSiteBinder.UpdateLabel); #if DEBUG // put the AST into the constant pool for debugging purposes updLabel = Expression.Block( Expression.Constant(binding, typeof(Expression)), updLabel ); #endif body.Add(updLabel); body.Add( Expression.Label( signature.ReturnLabel, Expression.Condition( Expression.Call( typeof(CallSiteOps).GetMethod("SetNotMatched"), @params.First() ), Expression.Default(signature.ReturnLabel.Type), Expression.Invoke( Expression.Property( Expression.Convert(site, siteType), typeof(CallSite ).GetProperty("Update") ), new TrueReadOnlyCollection (@params) ) ) ) ); return new Expression ( Expression.Block(body), "CallSite.Target", true, // always compile the rules with tail call optimization new TrueReadOnlyCollection (@params) ); } internal RuleCache GetRuleCache () where T : class { // make sure we have cache. if (Cache == null) { Interlocked.CompareExchange(ref Cache, new Dictionary (), null); } object ruleCache; var cache = Cache; lock (cache) { if (!cache.TryGetValue(typeof(T), out ruleCache)) { cache[typeof(T)] = ruleCache = new RuleCache (); } } RuleCache result = ruleCache as RuleCache ; Debug.Assert(result != null); return result; } } } // 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
- WebPartConnectionsConfigureVerb.cs
- StubHelpers.cs
- BufferedReadStream.cs
- RijndaelManaged.cs
- SapiRecoContext.cs
- DBConnection.cs
- KeyManager.cs
- IisTraceWebEventProvider.cs
- Property.cs
- BitmapFrameEncode.cs
- OpenFileDialog.cs
- HwndSourceParameters.cs
- SectionRecord.cs
- CodeChecksumPragma.cs
- CompensateDesigner.cs
- TemplateControlCodeDomTreeGenerator.cs
- TextBoxBase.cs
- ApplicationServicesHostFactory.cs
- LogWriteRestartAreaAsyncResult.cs
- XmlSchemaSimpleTypeList.cs
- ExpandCollapseProviderWrapper.cs
- DateTimeConverter.cs
- basenumberconverter.cs
- Nullable.cs
- DiagnosticTrace.cs
- SqlProfileProvider.cs
- PropertyPathConverter.cs
- SqlExpander.cs
- RuleValidation.cs
- BaseDataList.cs
- PeerNameRegistration.cs
- OdbcException.cs
- SafeWaitHandle.cs
- DropDownButton.cs
- ButtonChrome.cs
- Animatable.cs
- TextServicesHost.cs
- Error.cs
- XmlSchemaSet.cs
- WebConvert.cs
- TextRenderer.cs
- PinProtectionHelper.cs
- CodeRemoveEventStatement.cs
- NativeMethods.cs
- TreeViewAutomationPeer.cs
- BindingValueChangedEventArgs.cs
- DataGridLinkButton.cs
- ClientScriptManager.cs
- panel.cs
- DbConnectionStringBuilder.cs
- KeySpline.cs
- PropertyChangedEventManager.cs
- ResourceDefaultValueAttribute.cs
- PolicyConversionContext.cs
- HtmlTable.cs
- ProxyElement.cs
- CompleteWizardStep.cs
- DrawingContext.cs
- ViewStateException.cs
- XmlWhitespace.cs
- DiscardableAttribute.cs
- MembershipValidatePasswordEventArgs.cs
- Point.cs
- WebBrowserDocumentCompletedEventHandler.cs
- WmlLiteralTextAdapter.cs
- GlyphRun.cs
- AttachedPropertyDescriptor.cs
- IteratorFilter.cs
- SapiRecoInterop.cs
- UpdateCommand.cs
- CookielessHelper.cs
- MailWriter.cs
- GeometryModel3D.cs
- ColumnBinding.cs
- SchemaInfo.cs
- RowToParametersTransformer.cs
- coordinatorscratchpad.cs
- RootAction.cs
- ListControl.cs
- ObjectDataProvider.cs
- HostingEnvironmentException.cs
- documentation.cs
- AssociationSet.cs
- _LazyAsyncResult.cs
- BamlTreeMap.cs
- RedirectionProxy.cs
- DataProtection.cs
- MaterialGroup.cs
- MobileControlDesigner.cs
- SqlTriggerAttribute.cs
- FigureParagraph.cs
- ListSortDescription.cs
- ThumbButtonInfoCollection.cs
- TextSelectionHighlightLayer.cs
- StickyNoteAnnotations.cs
- DesignTimeResourceProviderFactoryAttribute.cs
- SignatureHelper.cs
- TextWriter.cs
- StorageEntityContainerMapping.cs
- GenericTextProperties.cs