internal static Func<IInspectable, object> CreateTypedRcwFactory(string runtimeClassName) { // If runtime class name is empty or "Object", then just use IInspectable. if (string.IsNullOrEmpty(runtimeClassName) || runtimeClassName == "Object") { return (IInspectable obj) => obj; } // PropertySet and ValueSet can return IReference<String> but Nullable<String> is illegal if (runtimeClassName == "Windows.Foundation.IReference`1<String>") { return (IInspectable obj) => new ABI.System.Nullable<String>(obj.ObjRef); } else if (runtimeClassName == "Windows.Foundation.IReference`1<Windows.UI.Xaml.Interop.TypeName>") { return (IInspectable obj) => new ABI.System.Nullable<Type>(obj.ObjRef); } Type implementationType = null; try { (implementationType, _) = TypeNameSupport.FindTypeByName(runtimeClassName.AsSpan()); } catch (TypeLoadException) { // If we reach here, then we couldn't find a type that matches the runtime class name. // Fall back to using IInspectable directly. return (IInspectable obj) => obj; } if (implementationType.IsGenericType && implementationType.GetGenericTypeDefinition() == typeof(System.Collections.Generic.KeyValuePair<,>)) { return CreateKeyValuePairFactory(implementationType); } if (implementationType.IsValueType) { if (IsNullableT(implementationType)) { return CreateNullableTFactory(implementationType); } else { return CreateNullableTFactory(typeof(System.Nullable<>).MakeGenericType(implementationType)); } } else if (IsIReferenceArray(implementationType)) { return CreateArrayFactory(implementationType); } return CreateFactoryForImplementationType(runtimeClassName, implementationType); }
internal static string GetRuntimeClassForTypeCreation(IInspectable inspectable, Type staticallyDeterminedType) { string runtimeClassName = inspectable.GetRuntimeClassName(noThrow: true); if (staticallyDeterminedType != null && staticallyDeterminedType != typeof(object)) { // We have a static type which we can use to construct the object. But, we can't just use it for all scenarios // and primarily use it for tear off scenarios and for scenarios where runtimeclass isn't accurate. // For instance if the static type is an interface, we return an IInspectable to represent the interface. // But it isn't convertable back to the class via the as operator which would be possible if we use runtimeclass. // Similarly for composable types, they can be statically retrieved using the parent class, but can then no longer // be cast to the sub class via as operator even if it is really an instance of it per rutimeclass. // To handle these scenarios, we use the runtimeclass if we find it is assignable to the statically determined type. // If it isn't, we use the statically determined type as it is a tear off. Type implementationType = null; if (!string.IsNullOrEmpty(runtimeClassName)) { try { (implementationType, _) = TypeNameSupport.FindTypeByName(runtimeClassName.AsSpan()); } catch (TypeLoadException) { } } if (!(implementationType != null && (staticallyDeterminedType == implementationType || staticallyDeterminedType.IsAssignableFrom(implementationType) || staticallyDeterminedType.IsGenericType && implementationType.GetInterfaces().Any(i => i.IsGenericType && i.GetGenericTypeDefinition() == staticallyDeterminedType.GetGenericTypeDefinition())))) { runtimeClassName = TypeNameSupport.GetNameForType(staticallyDeterminedType, TypeNameGenerationFlags.GenerateBoxedName); } } return runtimeClassName; }
public static void RegisterProjectionAssembly(Assembly assembly) => TypeNameSupport.RegisterProjectionAssembly(assembly);
internal InspectableInfo(Type type, Guid[] iids) { runtimeClassName = new Lazy<string>(() => TypeNameSupport.GetNameForType(type, TypeNameGenerationFlags.GenerateBoxedName | TypeNameGenerationFlags.NoCustomTypeName)); IIDs = iids; }