| FazBrowse GitHub Viewer | Trending | | Home |
| Tools: [Download Repo ZIP] [Original HTTPS Page] |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -21,6 +21,7 @@ This document follows the conventions laid out in [Keep a CHANGELOG][]. | |||
| 21 | 21 | - `__name__` and `__signature__` to reflected .NET methods | |
| 22 | 22 | - .NET collection types now implement standard Python collection interfaces from `collections.abc`. | |
| 23 | 23 | See [Mixins/collections.py](src/runtime/Mixins/collections.py). | |
| 24 | + - you can cast objects to generic .NET interfaces without specifying generic arguments as long as there is no ambiguity. | ||
| 24 | 25 | - .NET arrays implement Python buffer protocol | |
| 25 | 26 | - Python integer interoperability with `System.Numerics.BigInteger` | |
| 26 | 27 | - Python.NET will correctly resolve .NET methods, that accept `PyList`, `PyInt`, | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -1,4 +1,5 @@ | |||
| 1 | 1 | using System; | |
| 2 | + using System.Linq; | ||
| 2 | 3 | ||
| 3 | 4 | namespace Python.Runtime | |
| 4 | 5 | { | |
@@ -20,10 +21,58 @@ internal GenericType(Type tp) : base(tp) | |||
| 20 | 21 | /// </summary> | |
| 21 | 22 | public static NewReference tp_new(BorrowedReference tp, BorrowedReference args, BorrowedReference kw) | |
| 22 | 23 | { | |
| 24 | + var self = (GenericType)GetManagedObject(tp)!; | ||
| 25 | + if (!self.type.Valid) | ||
| 26 | + { | ||
| 27 | + return Exceptions.RaiseTypeError(self.type.DeletedMessage); | ||
| 28 | + } | ||
| 29 | + var type = self.type.Value; | ||
| 30 | + | ||
| 31 | + if (type.IsInterface && !type.IsConstructedGenericType) | ||
| 32 | + { | ||
| 33 | + var nargs = Runtime.PyTuple_Size(args); | ||
| 34 | + if (nargs == 1) | ||
| 35 | + { | ||
| 36 | + var instance = Runtime.PyTuple_GetItem(args, 0); | ||
| 37 | + return AsGenericInterface(instance, type); | ||
| 38 | + } | ||
| 39 | + } | ||
| 40 | + | ||
| 23 | 41 | Exceptions.SetError(Exceptions.TypeError, "cannot instantiate an open generic type"); | |
| 42 | + | ||
| 24 | 43 | return default; | |
| 25 | 44 | } | |
| 26 | 45 | ||
| 46 | + static NewReference AsGenericInterface(BorrowedReference instance, Type targetType) | ||
| 47 | + { | ||
| 48 | + if (GetManagedObject(instance) is not CLRObject obj) | ||
| 49 | + { | ||
| 50 | + return Exceptions.RaiseTypeError("only .NET objects can be cast to .NET interfaces"); | ||
| 51 | + } | ||
| 52 | + | ||
| 53 | + Type[] supportedInterfaces = obj.inst.GetType().GetInterfaces(); | ||
| 54 | + Type[] constructedInterfaces = supportedInterfaces | ||
| 55 | + .Where(i => i.IsConstructedGenericType && i.GetGenericTypeDefinition() == targetType) | ||
| 56 | + .ToArray(); | ||
| 57 | + | ||
| 58 | + if (constructedInterfaces.Length == 1) | ||
| 59 | + { | ||
| 60 | + BorrowedReference pythonic = ClassManager.GetClass(constructedInterfaces[0]); | ||
| 61 | + using var args = Runtime.PyTuple_New(1); | ||
| 62 | + Runtime.PyTuple_SetItem(args.Borrow(), 0, instance); | ||
| 63 | + return Runtime.PyObject_CallObject(pythonic, args.Borrow()); | ||
| 64 | + } | ||
| 65 | + | ||
| 66 | + if (constructedInterfaces.Length > 1) | ||
| 67 | + { | ||
| 68 | + string interfaces = string.Join(", ", constructedInterfaces.Select(TypeManager.GetPythonTypeName)); | ||
| 69 | + return Exceptions.RaiseTypeError("Ambiguous cast to .NET interface. " | ||
| 70 | + + $"Object implements: {interfaces}"); | ||
| 71 | + } | ||
| 72 | + | ||
| 73 | + return Exceptions.RaiseTypeError("object does not implement " | ||
| 74 | + + TypeManager.GetPythonTypeName(targetType)); | ||
| 75 | + } | ||
| 27 | 76 | ||
| 28 | 77 | /// <summary> | |
| 29 | 78 | /// Implements __call__ for reflected generic types. | |
| Back | FazBrowse Home | New Git URL |
0 commit comments