Hello,
This PR<https://github.com/pythonnet/pythonnet/pull/1240> changed behavior of
pythonnet to use stricter typing when a method returns an interface. I'd like
a way to opt-out of this behavior, and I'll share a representative use-case
below. The tl;dr is that python is a dynamic language and I expect the C#
objects which pythonnet wraps to behave more like "dynamic" and less like the
static types on the interface.
**** C# code ****
namespace Example1
{
public enum ShapeType
{
Square,
Circle
}
public interface IShape
{
void Draw();
double Area { get; }
ShapeType Type { get; }
}
public class Square : IShape
{
public double Length { get; }
public Square(double length)
{
Length = length;
}
public void Draw() {}
public double Area { get { return Length * Length; } }
public ShapeType Type { get { return ShapeType.Square; } }
}
public class Circle : IShape
{
public double Radius { get; }
public Circle(double radius)
{
Radius = radius;
}
public void Draw() {}
public double Area { get { return Math.PI * Radius * Radius; } }
public ShapeType Type { get { return ShapeType.Circle; } }
}
public class ShapeDataModel
{
private Dictionary<int, IShape> _shapes = new Dictionary<int, IShape>();
private int _nextId = 1;
public int AddShape(IShape shape)
{
int id = _nextId;
_shapes[id] = shape;
_nextId++;
return id;
}
public IShape GetShape(int id)
{
return _shapes[id];
}
}
}
**** Python code ****
>>> import clr
>>> clr.AddReference("Example1")
>>> import Example1
>>> sq1 = Example1.Square(2.)
>>> ci1 = Example1.Circle(1.3)
>>> sq2 = Example1.Square(2.5)
>>> m = Example1.ShapeDataModel()
>>> m.AddShape(sq1)
1
>>> m.AddShape(sq2)
2
>>> m.AddShape(ci1)
3
>>> m.GetShape(2)
<Example1.IShape object at 0x000002A3448A09A0>
>>> m.GetShape(2).Area
6.25
>>> m.GetShape(2).Length
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: 'IShape' object has no attribute 'Length'
**** summary ****
This factory and/or datamodel pattern is very common in my codebase and
probably also lots of object oriented systems. The mentioned PR breaks this
common design pattern in C# objects wrapped by pythonnet, and I would like a
way to opt-out of it. Maybe an attribute on the method which returns an
interface can be used, or maybe something global to switch this behavior. I
think perhaps the original bug might also have been fixed in a different way.
Thanks!
Mohamed
_______________________________________________
PythonNet mailing list -- [email protected]
To unsubscribe send an email to [email protected]
https://mail.python.org/mailman3/lists/pythonnet.python.org/
Member address: [email protected]