MemberTracker.cs :  » Script » IronRuby » Microsoft » Scripting » Actions » C# / CSharp Open Source

Home
C# / CSharp Open Source
1.2.6.4 mono .net core
2.2.6.4 mono core
3.Aspect Oriented Frameworks
4.Bloggers
5.Build Systems
6.Business Application
7.Charting Reporting Tools
8.Chat Servers
9.Code Coverage Tools
10.Content Management Systems CMS
11.CRM ERP
12.Database
13.Development
14.Email
15.Forum
16.Game
17.GIS
18.GUI
19.IDEs
20.Installers Generators
21.Inversion of Control Dependency Injection
22.Issue Tracking
23.Logging Tools
24.Message
25.Mobile
26.Network Clients
27.Network Servers
28.Office
29.PDF
30.Persistence Frameworks
31.Portals
32.Profilers
33.Project Management
34.RSS RDF
35.Rule Engines
36.Script
37.Search Engines
38.Sound Audio
39.Source Control
40.SQL Clients
41.Template Engines
42.Testing
43.UML
44.Web Frameworks
45.Web Service
46.Web Testing
47.Wiki Engines
48.Windows Presentation Foundation
49.Workflows
50.XML Parsers
C# / C Sharp
C# / C Sharp by API
C# / CSharp Tutorial
C# / CSharp Open Source » Script » IronRuby 
IronRuby » Microsoft » Scripting » Actions » MemberTracker.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;
using System.Collections.Generic;
using System.Dynamic;
using System.Reflection;

using Microsoft.Scripting.Actions.Calls;
using Microsoft.Scripting.Runtime;
using Microsoft.Scripting.Utils;

namespace Microsoft.Scripting.Actions{
    /// <summary>
    /// Represents a logical member of a type.  The member could either be real concrete member on a type or
    /// an extension member.
    /// 
    /// This seperates the "physical" members that .NET knows exist on types from the members that
    /// logically exist on a type.  It also provides other abstractions above the level of .NET reflection
    /// such as MemberGroups and NamespaceTracker's.
    /// 
    /// It also provides a wrapper around the reflection APIs which cannot be extended from partial trust.
    /// </summary>
    public abstract class MemberTracker {
        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Security", "CA2105:ArrayFieldsShouldNotBeReadOnly")]
        public static readonly MemberTracker[] EmptyTrackers = new MemberTracker[0];

        private static readonly Dictionary<MemberKey, MemberTracker> _trackers = new Dictionary<MemberKey, MemberTracker>();

        /// <summary>
        /// We ensure we only produce one MemberTracker for each member which logically lives on the declaring type.  So 
        /// for example if you get a member from a derived class which is declared on the base class it should be the same 
        /// as getting the member from the base class.  Thats easy enough until you get into extension members  here there
        /// might be one extension member which is being applied to multiple types.  Therefore we need to take into account the 
        /// extension type when ensuring that we only have 1 MemberTracker ever created.
        /// </summary>
        class MemberKey {
            private readonly MemberInfo Member;
            private readonly Type Extending;

            public MemberKey(MemberInfo member, Type extending) {
                Member = member;
                Extending = extending;
            }

            public override int GetHashCode() {
                int res = Member.GetHashCode();
                if (Extending != null) {
                    res ^= Extending.GetHashCode();
                }
                return res;
            }

            public override bool Equals(object obj) {
                MemberKey other = obj as MemberKey;
                if (other == null) return false;

                return other.Member == Member &&
                    other.Extending == Extending;
            }
        }

        internal MemberTracker() {
        }

        /// <summary>
        /// The type of member tracker.
        /// </summary>
        public abstract TrackerTypes MemberType {
            get;
        }

        /// <summary>
        /// The logical declaring type of the member.
        /// </summary>
        public abstract Type DeclaringType {
            get;
        }

        /// <summary>
        /// The name of the member.
        /// </summary>
        public abstract string Name {
            get;
        }

        public static MemberTracker FromMemberInfo(MemberInfo member) {
            return FromMemberInfo(member, null);
        }

        public static MemberTracker FromMemberInfo(MemberInfo member, Type extending) {
            ContractUtils.RequiresNotNull(member, "member");

            lock (_trackers) {
                MemberTracker res;
                MemberKey key = new MemberKey(member, extending);
                if (_trackers.TryGetValue(key, out res)) return res;

                switch (member.MemberType) {
                    case MemberTypes.Constructor: res = new ConstructorTracker((ConstructorInfo)member); break;
                    case MemberTypes.Event: res = new EventTracker((EventInfo)member); break;
                    case MemberTypes.Field: res = new FieldTracker((FieldInfo)member); break;
                    case MemberTypes.Method:
                        MethodInfo mi = (MethodInfo)member;
                        if (extending != null) {
                            res = new ExtensionMethodTracker(mi, member.IsDefined(typeof(StaticExtensionMethodAttribute), false), extending);
                        } else {
                            res = new MethodTracker(mi);
                        }
                        break;
                    case MemberTypes.TypeInfo:
                    case MemberTypes.NestedType: res = new NestedTypeTracker((Type)member); break;
                    case MemberTypes.Property: res = new ReflectedPropertyTracker((PropertyInfo)member); break;
                    default: throw Error.UnknownMemberType(member.MemberType);
                }

                _trackers[key] = res;
                return res;
            }
        }

        #region Public expression builders

        /// <summary>
        /// Gets the expression that creates the value.  
        /// 
        /// Returns null if it's an error to get the value.  The caller can then call GetErrorForGet to get 
        /// the correct error Expression (or null if they should provide a default).
        /// </summary>
        public virtual DynamicMetaObject GetValue(OverloadResolverFactory resolverFactory, ActionBinder binder, Type type) {
            return binder.ReturnMemberTracker(type, this);
        }

        /// <summary>
        /// Gets an expression that assigns a value to the left hand side.
        /// 
        /// Returns null if it's an error to assign to.  The caller can then call GetErrorForSet to
        /// get the correct error Expression (or null if a default error should be provided).
        /// </summary>
        public virtual DynamicMetaObject SetValue(OverloadResolverFactory resolverFactory, ActionBinder binder, Type type, DynamicMetaObject value) {
            return null;
        }

        /// <summary>
        /// Gets an expression that performs a call on the object using the specified arguments.
        /// 
        /// Returns null if it's an error to perform the specific operation.  The caller can then call 
        /// GetErrorsForDoCall to get the correct error Expression (or null if a default error should be provided).
        /// </summary>
        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1716:IdentifiersShouldNotMatchKeywords", MessageId = "Call")] // TODO: fix
        internal virtual DynamicMetaObject Call(OverloadResolverFactory resolverFactory, ActionBinder binder, params DynamicMetaObject[] arguments) {
            return null;
        }

        #endregion

        #region Public error expression builders

        /// <summary>
        /// Returns the error associated with getting the value.  
        /// 
        /// A null return value indicates that the default error message should be provided by the caller.
        /// </summary>
        public virtual ErrorInfo GetError(ActionBinder binder) {
            return null;
        }

        /// <summary>
        /// Returns the error associated with accessing this member via a bound instance.
        /// 
        /// A null return value indicates that the default error message should be provided by the caller.
        /// </summary>
        public virtual ErrorInfo GetBoundError(ActionBinder binder, DynamicMetaObject instance) {
            return null;
        }

        /// <summary>
        /// Helper for getting values that have been bound.  Called from BoundMemberTracker.  Custom member
        /// trackers can override this to provide their own behaviors when bound to an instance.
        /// </summary>
        protected internal virtual DynamicMetaObject GetBoundValue(OverloadResolverFactory resolverFactory, ActionBinder binder, Type type, DynamicMetaObject instance) {
            return GetValue(resolverFactory, binder, type);
        }

        /// <summary>
        /// Helper for setting values that have been bound.  Called from BoundMemberTracker.  Custom member
        /// trackers can override this to provide their own behaviors when bound to an instance.
        /// </summary>
        protected internal virtual DynamicMetaObject SetBoundValue(OverloadResolverFactory resolverFactory, ActionBinder binder, Type type, DynamicMetaObject value, DynamicMetaObject instance) {
            return SetValue(resolverFactory, binder, type, instance);
        }

        /// <summary>
        /// Binds the member tracker to the specified instance rturning a new member tracker if binding 
        /// is possible.  If binding is not possible the existing member tracker will be returned.  For example
        /// binding to a static field results in returning the original MemberTracker.  Binding to an instance
        /// field results in a new BoundMemberTracker which will get GetBoundValue/SetBoundValue to pass the
        /// instance through.
        /// </summary>
        public virtual MemberTracker BindToInstance(DynamicMetaObject instance) {
            return this;
        }

        #endregion
    }
}
www.java2v.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.