예제 #1
0
        /// <summary>
        /// Gets the DuckProxyType&lt;TInterface&gt; object for a given duck type.
        /// </summary>
        /// <remarks>
        /// First, the most general type in the inheritance chain of the given type that implements all the
        /// members of TInterface is selected.  Then if a proxy type has already been generated, it returns
        /// it.  Finally, if not, it creates a new object and adds it to the dictionary.
        /// </remarks>
        /// <param name="duckType">Type of object being casted.</param>
        /// <returns>The duck proxy type to use to cast or prepare for casting.</returns>
        private static DuckProxyType <TInterface> GetProxyType(Type duckType)
        {
            DuckProxyType <TInterface> proxyType = null;

            // Examine the duck type's inheritance chain.
            List <Type> inheritanceChain = new List <Type>();
            Type        baseType         = duckType;

            do
            {
                inheritanceChain.Add(baseType);
                baseType = baseType.BaseType;
            }while (baseType != null);

            // Iterate the inheritance chain backwards (most general to most specialized) to find a proxy type
            // that has already been generated.
            for (int i = inheritanceChain.Count - 1; i >= 0; i--)
            {
                Type type = inheritanceChain[i];

                if (s_ProxyTypes.ContainsKey(type))
                {
                    proxyType = s_ProxyTypes[type];
                    break;
                }
            }

            if (proxyType == null)
            {
                // Iterate the inheritance chain backwards (most general to most specialized) to find the most
                // general type that can be casted to TInterface.
                for (int i = inheritanceChain.Count - 1; i >= 0; i--)
                {
                    Type type = inheritanceChain[i];

                    if (CanCast(type))
                    {
                        proxyType = new DuckProxyType <TInterface>(type);
                        break;
                    }
                }

                if (proxyType == null)
                {
                    // If proxyType is null, then DuckTyping.CanCast<>() returned false for every type in the
                    // inheritance chain.  The following line will cause an exception to be thrown when
                    // GenerateProxyType() is called.  The exception will indicate why the duck cannot be casted.
                    proxyType = new DuckProxyType <TInterface>(duckType);
                }
                else
                {
                    // If we got to this point, the cast is valid and it is ok to add the proxy type to the dictionary.
                    s_ProxyTypes.Add(proxyType.m_DuckType, proxyType);
                }
            }

            return(proxyType);
        }
예제 #2
0
        /// <summary>
        /// Calls the static WrapDuck method of the generated proxy type to initialize a new instance of
        /// the proxy type with a given duck object.
        /// </summary>
        /// <param name="duck">Duck object that the new proxy object should forward calls to.</param>
        /// <returns>
        /// An instance of the proxy type, which implements TInterface, initialized with the given duck
        /// object.
        /// </returns>
        internal static TInterface WrapDuck(object duck)
        {
            DuckProxyType <TInterface> proxyType = GetProxyType(duck.GetType());

            // Make sure the proxy type is generated before we try to call it.
            proxyType.GenerateProxyType();

            // Call wrap method in the proxy type to create an instance of the proxy for the duck and return it.
            return(proxyType.m_WrapDuck(duck));
        }