/// <summary> /// Gets the InterfaceDuckProxyType object for a given cast. /// </summary> /// <param name="interfaceType">Type to cast to.</param> /// <param name="duckType">Static type being casted.</param> /// <returns>The duck proxy type to use to cast or prepare for casting.</returns> private InterfaceDuckProxyType GetProxyType(Type interfaceType, Type duckType) { InterfaceDuckProxyType proxyType = null; FromTypeTree <InterfaceDuckProxyType> fromTypeTree = null; if (s_ProxyTypeTree.ContainsKey(interfaceType)) { fromTypeTree = s_ProxyTypeTree[interfaceType]; if (fromTypeTree.ContainsKey(duckType)) { proxyType = fromTypeTree[duckType]; } } if (proxyType == null) { proxyType = new InterfaceDuckProxyType(interfaceType, duckType, true); if (fromTypeTree == null) { fromTypeTree = new FromTypeTree <InterfaceDuckProxyType>(); s_ProxyTypeTree.Add(interfaceType, fromTypeTree); } fromTypeTree.Add(proxyType.DuckType, proxyType); } return(proxyType); }
/// <summary> /// Gets the DelegateDuckProxyType object for a given duck type. /// </summary> /// <param name="toType">Type to be casted to.</param> /// <param name="fromType">Type of delegate to be casted.</param> /// <returns>The duck proxy type to use to cast or prepare for casting.</returns> private static DelegateDuckProxyType GetProxyType(Type toType, Type fromType) { DelegateDuckProxyType proxyType = null; FromTypeTree <DelegateDuckProxyType> fromTypeTree = null; if (s_ProxyTypeTree.ContainsKey(toType)) { fromTypeTree = s_ProxyTypeTree[toType]; if (fromTypeTree.ContainsKey(fromType)) { proxyType = fromTypeTree[fromType]; } } if (proxyType == null) { proxyType = new DelegateDuckProxyType(toType, fromType); if (proxyType.CanProxy()) { if (fromTypeTree == null) { fromTypeTree = new FromTypeTree <DelegateDuckProxyType>(); s_ProxyTypeTree.Add(toType, fromTypeTree); } fromTypeTree.Add(fromType, proxyType); } } return(proxyType); }
/// <summary> /// Determines whether a type can be casted to another type. /// </summary> /// <param name="toType">Type to cast to.</param> /// <param name="fromType">Type of object to be casted.</param> /// <returns>If an object of the given from type can be casted to the given to type, true; otherwise, false.</returns> public static bool CanCast(Type toType, Type fromType) { bool canCast; FromTypeTree <bool> canCastFromTree; if (s_CanCastTree.ContainsKey(toType)) { canCastFromTree = s_CanCastTree[toType]; } else { canCastFromTree = new FromTypeTree <bool>(); s_CanCastTree.Add(toType, canCastFromTree); } if (canCastFromTree.ContainsKey(fromType)) { canCast = canCastFromTree[fromType]; } else { canCast = CanNormalCast(toType, fromType, true); if (!canCast) { foreach (IDuckCaster caster in s_DuckCasters) { if (caster.CanCast(toType, fromType)) { canCast = true; break; } } } if (!canCast) { foreach (IDuckCaster caster in s_DuckCasters) { if (caster.CouldUncast(toType, fromType)) { canCast = true; break; } } } canCastFromTree.Add(fromType, canCast); } return(canCast); }
/// <summary> /// Determines whether a static type can be casted to another type. /// </summary> /// <param name="toType">Type to cast to.</param> /// <param name="staticType">Static type to be casted.</param> /// <returns>If the given static type can be casted to the given to type, true; otherwise, false.</returns> public static bool CanStaticCast(Type toType, Type staticType) { bool canCast; FromTypeTree <bool> canCastFromTree; if (s_CanStaticCastTree.ContainsKey(toType)) { canCastFromTree = s_CanStaticCastTree[toType]; } else { canCastFromTree = new FromTypeTree <bool>(); s_CanStaticCastTree.Add(toType, canCastFromTree); } if (canCastFromTree.ContainsKey(staticType)) { canCast = canCastFromTree[staticType]; } else { canCast = false; foreach (IStaticDuckCaster caster in s_StaticDuckCasters) { if (caster.CanStaticCast(toType, staticType)) { canCast = true; break; } } canCastFromTree.Add(staticType, canCast); } return(canCast); }
/// <summary> /// Gets the InterfaceDuckProxyType object for a given cast. /// </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="interfaceType">Type to cast to.</param> /// <param name="duckType">Type of object being casted.</param> /// <returns>The duck proxy type to use to cast or prepare for casting.</returns> private InterfaceDuckProxyType GetProxyType(Type interfaceType, Type duckType) { InterfaceDuckProxyType proxyType = null; FromTypeTree <InterfaceDuckProxyType> fromTypeTree = 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); // Include interfaces in the inheritance chain. We don't know which order, but it will still help. /*Type[] interfaces = duckType.GetInterfaces(); * foreach (Type _interface in interfaces) * { * inheritanceChain.Add(_interface); * }*/ if (s_ProxyTypeTree.ContainsKey(interfaceType)) { fromTypeTree = s_ProxyTypeTree[interfaceType]; // 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 (fromTypeTree.ContainsKey(type)) { proxyType = fromTypeTree[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(interfaceType, type)) { proxyType = new InterfaceDuckProxyType(interfaceType, type, false); 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 InterfaceDuckProxyType(interfaceType, duckType, false); } else { // If we got to this point, the cast is valid and it is ok to add the proxy type to the tree. if (fromTypeTree == null) { fromTypeTree = new FromTypeTree <InterfaceDuckProxyType>(); s_ProxyTypeTree.Add(interfaceType, fromTypeTree); } fromTypeTree.Add(proxyType.DuckType, proxyType); } } return(proxyType); }