[Python.NET] Re: Wrap in interface (#1240)
Mohamed Koubaa <[email protected]> Mon, 8 Feb 2021 15:31:33 +0000
| Newsgroups | gmane.comp.python.dotnet |
|---|---|
| Message-ID | <SN6PR01MB4976CCEE1E29E0FC89CE0CC8998F9@SN6PR01MB4976.prod.exchangelabs.com> |
--===============4369368159843712820== Content-Language: en-US Content-Type: multipart/alternative; boundary="_000_SN6PR01MB4976CCEE1E29E0FC89CE0CC8998F9SN6PR01MB4976prod_" --_000_SN6PR01MB4976CCEE1E29E0FC89CE0CC8998F9SN6PR01MB4976prod_ Content-Type: text/plain; charset="Windows-1252" Content-Transfer-Encoding: quoted-printable Victor, Sorry for the late response. I think what I would need is some kind of fla= g in the python runtime to choose the old behavior (without having to have = my own branch). Of course there is a workaround but we've invested a lot o= f time in designing the API for both CPython & IronPython and it would be i= deal if they did not differ in this way. This could be a global flag on the runtime and/or an attribute on a class/i= nterface to decide on a granular level whether the specific class/interface= will use interface method binding or instance method binding. Thoughts? Thanks! Mohamed ________________________________ From: Victor =93LOST=94 Milovanov <[email protected]> Sent: Monday, November 2, 2020 8:35 PM To: A list for users and developers of Python.NET <[email protected]> Subject: [Python.NET] Re: Wrap in interface (#1240) [External Sender] The original bug report described a similar problem, except the behavior wi= thout defaulting to stricter interface types is very unintuitive. Imagine y= ou have a well documented library, that exposes property Prop of type IInte= rface. When specific class implements some Method in IInterface explicitly= (which arguably is a very minor implementation detail), and you call Prop.= Method() in Python, it can fail with AttributeError despite the documentati= on claiming this method exists on the interface. This is very confusing. IM= HO, more confusing, than inability to get Length of an element of IShape[]. We could try to improve the situation for Python folks by allowing interfac= e instance wrappers to fall back to the original class instance in case the= attribute is not found in the interface itself. I think this might still b= e problematic, as it would make the behavior of hasattr and other similar f= unctions a bit surprising. Regardless, there=92s a workaround for the scenario you described which is = just doing m.GetShape(1).__raw_implementation__.Length or m.GetShape(1).__implementation__.Length depending if you need an encoded in= stance. Regards, Victor Milovanov From: Mohamed Koubaa<mailto:[email protected]> Sent: Monday, November 2, 2020 6:15 PM To: [email protected]<mailto:[email protected]> Subject: [Python.NET] Wrap in interface (#1240) Hello, This PR<https://nam10.safelinks.protection.outlook.com/?url=3Dhttps%3A%2F%2= Fgithub.com%2Fpythonnet%2Fpythonnet%2Fpull%2F1240&data=3D04%7C01%7Cmohamed.= koubaa%40ansys.com%7C37b0dd3831f140993f6008d87fa1418f%7C34c6ce6715b84eff80e= 952da8be89706%7C0%7C0%7C637399677854765584%7CUnknown%7CTWFpbGZsb3d8eyJWIjoi= MC4wLjAwMDAiLCJQIjoiV2luMzIiLCJBTiI6Ik1haWwiLCJXVCI6Mn0%3D%7C1000&sdata=3Dt= TftofPt0a7ds4g1qBjLIBXi7iFOgtygMW3Xa3WHF%2Fo%3D&reserved=3D0> changed behav= ior 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 representati= ve use-case below. The tl;dr is that python is a dynamic language and I ex= pect 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 =3D 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 =3D 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 =3D new Dictionary<int, ISh= ape>(); private int _nextId =3D 1; public int AddShape(IShape shape) { int id =3D _nextId; _shapes[id] =3D shape; _nextId++; return id; } public IShape GetShape(int id) { return _shapes[id]; } } } **** Python code **** >>> import clr >>> clr.AddReference("Example1") >>> import Example1 >>> sq1 =3D Example1.Square(2.) >>> ci1 =3D Example1.Circle(1.3) >>> sq2 =3D Example1.Square(2.5) >>> m =3D 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 pro= bably also lots of object oriented systems. The mentioned PR breaks this c= ommon 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 i= nterface 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 w= ay. Thanks! Mohamed --_000_SN6PR01MB4976CCEE1E29E0FC89CE0CC8998F9SN6PR01MB4976prod_ Content-Type: text/html; charset="Windows-1252" Content-Transfer-Encoding: quoted-printable <html> <head> <meta http-equiv=3D"Content-Type" content=3D"text/html; charset=3DWindows-1= 252"> <style type=3D"text/css" style=3D"display:none;"> P {margin-top:0;margin-bo= ttom:0;} </style> </head> <body dir=3D"ltr"> <div style=3D"font-family: Calibri, Arial, Helvetica, sans-serif; font-size= : 12pt; color: rgb(0, 0, 0);"> Victor,</div> <div style=3D"font-family: Calibri, Arial, Helvetica, sans-serif; font-size= : 12pt; color: rgb(0, 0, 0);"> <br> </div> <div style=3D"font-family: Calibri, Arial, Helvetica, sans-serif; font-size= : 12pt; color: rgb(0, 0, 0);"> Sorry for the late response. I think what I would need is some kind o= f flag in the python runtime to choose the old behavior (without having to = have my own branch). Of course there is a workaround but we've invest= ed a lot of time in designing the API for both CPython & IronPython and it would be ideal if they did not differ= in this way. </div> <div style=3D"font-family: Calibri, Arial, Helvetica, sans-serif; font-size= : 12pt; color: rgb(0, 0, 0);"> <br> </div> <div style=3D"font-family: Calibri, Arial, Helvetica, sans-serif; font-size= : 12pt; color: rgb(0, 0, 0);"> This could be a global flag on the runtime and/or an attribute on a class/i= nterface to decide on a granular level whether the specific class/interface= will use interface method binding or instance method binding.</div> <div style=3D"font-family: Calibri, Arial, Helvetica, sans-serif; font-size= : 12pt; color: rgb(0, 0, 0);"> <br> </div> <div style=3D"font-family: Calibri, Arial, Helvetica, sans-serif; font-size= : 12pt; color: rgb(0, 0, 0);"> Thoughts?</div> <div style=3D"font-family: Calibri, Arial, Helvetica, sans-serif; font-size= : 12pt; color: rgb(0, 0, 0);"> <br> </div> <div style=3D"font-family: Calibri, Arial, Helvetica, sans-serif; font-size= : 12pt; color: rgb(0, 0, 0);"> Thanks!</div> <div style=3D"font-family: Calibri, Arial, Helvetica, sans-serif; font-size= : 12pt; color: rgb(0, 0, 0);"> Mohamed</div> <div id=3D"appendonsend"></div> <hr style=3D"display:inline-block;width:98%" tabindex=3D"-1"> <div id=3D"divRplyFwdMsg" dir=3D"ltr"><font face=3D"Calibri, sans-serif" st= yle=3D"font-size:11pt" color=3D"#000000"><b>From:</b> Victor =93LOST=94 Mil= ovanov <[email protected]><br> <b>Sent:</b> Monday, November 2, 2020 8:35 PM<br> <b>To:</b> A list for users and developers of Python.NET <pythonnet@pyth= on.org><br> <b>Subject:</b> [Python.NET] Re: Wrap in interface (#1240)</font> <div> </div> </div> <style> <!-- @font-face {font-family:"Cambria Math"} @font-face {font-family:Calibri} p.x_MsoNormal, li.x_MsoNormal, div.x_MsoNormal {margin:0in; font-size:11.0pt; font-family:"Calibri",sans-serif} a:link, span.x_MsoHyperlink {color:blue; text-decoration:underline} .x_MsoChpDefault {} @page WordSection1 {margin:1.0in 1.0in 1.0in 1.0in} div.x_WordSection1 {} --> </style> <div lang=3D"EN-US" link=3D"blue" vlink=3D"#954F72"> <div style=3D"border:solid #9C6500 1.0pt; padding:2.0pt 2.0pt 2.0pt 2.0pt"> <p style=3D"line-height:12.0pt; background:#FFEB9C"><b><span lang=3D"EN-US"= style=3D"font-size:10.0pt; color:red">[External Sender]</span></b></p> </div> <div> <div class=3D"x_WordSection1"> <p class=3D"x_MsoNormal">The original bug report described a similar proble= m, except the behavior without defaulting to stricter interface types is ve= ry unintuitive. Imagine you have a well documented library, that exposes pr= operty <b>Prop</b> of type <b>IInterface</b>. When specific class implements some = <b>Method</b> in <b>IInterface</b> explicitly (which arguably is a very minor implementation= detail), and you call <b>Prop.Method()</b> in Python, it can fail with AttributeError despite the= documentation claiming this method exists on the interface. This is very c= onfusing. IMHO, more confusing, than inability to get Length of an element = of <b>IShape[]</b>.<b></b></p> <p class=3D"x_MsoNormal"> </p> <p class=3D"x_MsoNormal">We could try to improve the situation for Python f= olks by allowing interface instance wrappers to fall back to the original c= lass instance in case the attribute is not found in the interface itself. I= think this might still be problematic, as it would make the behavior of hasattr and other similar functions a bit= surprising.</p> <p class=3D"x_MsoNormal"> </p> <p class=3D"x_MsoNormal">Regardless, there=92s a workaround for the scenari= o you described which is just doing <b>m.GetShape(1).__raw_implementation__.Length </b>or </p> <p class=3D"x_MsoNormal"><b>m.GetShape(1).__implementation__.Length </b>dep= ending if you need an encoded instance.</p> <p class=3D"x_MsoNormal"> </p> <p class=3D"x_MsoNormal">Regards,</p> <p class=3D"x_MsoNormal">Victor Milovanov</p> <p class=3D"x_MsoNormal"> </p> <div style=3D"border:none; border-top:solid #E1E1E1 1.0pt; padding:3.0pt 0i= n 0in 0in"> <p class=3D"x_MsoNormal" style=3D"border:none; padding:0in"><b>From: </b><a= href=3D"mailto:[email protected]">Mohamed Koubaa</a><br> <b>Sent: </b>Monday, November 2, 2020 6:15 PM<br> <b>To: </b><a href=3D"mailto:[email protected]">[email protected]</a>= <br> <b>Subject: </b>[Python.NET] Wrap in interface (#1240)</p> </div> <p class=3D"x_MsoNormal"> </p> <div> <p class=3D"x_MsoNormal"><span style=3D"font-size:12.0pt; color:black">Hell= o,</span></p> </div> <div> <p class=3D"x_MsoNormal"><span style=3D"font-size:12.0pt; color:black">&nbs= p;</span></p> </div> <div> <p class=3D"x_MsoNormal"><span style=3D"font-size:12.0pt; color:black">This= <a href=3D"https://nam10.safelinks.protection.outlook.com/?url=3Dhttps%3A%= 2F%2Fgithub.com%2Fpythonnet%2Fpythonnet%2Fpull%2F1240&data=3D04%7C01%7C= mohamed.koubaa%40ansys.com%7C37b0dd3831f140993f6008d87fa1418f%7C34c6ce6715b= 84eff80e952da8be89706%7C0%7C0%7C637399677854765584%7CUnknown%7CTWFpbGZsb3d8= eyJWIjoiMC4wLjAwMDAiLCJQIjoiV2luMzIiLCJBTiI6Ik1haWwiLCJXVCI6Mn0%3D%7C1000&a= mp;sdata=3DtTftofPt0a7ds4g1qBjLIBXi7iFOgtygMW3Xa3WHF%2Fo%3D&reserved=3D= 0" originalsrc=3D"https://github.com/pythonnet/pythonnet/pull/1240" shash= =3D"vyYsgvINGSLnbes6L+4y1TCDW2teH/FYnmyj7SFODfIeLPJzQgO6AGw063VtEJpo11HNOUx= 5cJm1Ma5L3JT0AEfBx4DoESrAQOVD38aWZKs9m3GDjW+LRuwAgaI6RhSn2MUCDYcA+OVRciE8Um= F/KzufoAS32Xul+y3Zw9cj08E=3D" title=3D"https://github.com/pythonnet/pythonn= et/pull/1240"> PR</a> changed behavior of pythonnet to use stricter typing when a met= hod 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 py= thon 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.</span></p> </div> <div> <p class=3D"x_MsoNormal"><span style=3D"font-size:12.0pt; color:black">&nbs= p;</span></p> </div> <div> <p class=3D"x_MsoNormal"><span style=3D"font-size:12.0pt; color:black">****= C# code ****</span></p> </div> <div> <p class=3D"x_MsoNormal"><span style=3D"font-size:12.0pt; font-family:"= ;Courier New"; color:black">namespace Example1</span><span style=3D"fo= nt-size:12.0pt; color:black"> </span></p> <div> <p class=3D"x_MsoNormal"><span style=3D"font-size:12.0pt; font-family:"= ;Courier New"; color:black">{</span><span style=3D"font-size:12.0pt; c= olor:black"></span></p> </div> <div> <p class=3D"x_MsoNormal"><span style=3D"font-size:12.0pt; font-family:"= ;Courier New"; color:black"> public enum ShapeType</span>= <span style=3D"font-size:12.0pt; color:black"></span></p> </div> <div> <p class=3D"x_MsoNormal"><span style=3D"font-size:12.0pt; font-family:"= ;Courier New"; color:black"> {</span><span style=3D"font-= size:12.0pt; color:black"></span></p> </div> <div> <p class=3D"x_MsoNormal"><span style=3D"font-size:12.0pt; font-family:"= ;Courier New"; color:black"> Square,</span>= <span style=3D"font-size:12.0pt; color:black"></span></p> </div> <div> <p class=3D"x_MsoNormal"><span style=3D"font-size:12.0pt; font-family:"= ;Courier New"; color:black"> Circle</span><= span style=3D"font-size:12.0pt; color:black"></span></p> </div> <div> <p class=3D"x_MsoNormal"><span style=3D"font-size:12.0pt; font-family:"= ;Courier New"; color:black"> }</span><span style=3D"font-= size:12.0pt; color:black"></span></p> </div> <div> <p class=3D"x_MsoNormal"><span style=3D"font-size:12.0pt; font-family:"= ;Courier New"; color:black"> public interface IShape</spa= n><span style=3D"font-size:12.0pt; color:black"></span></p> </div> <div> <p class=3D"x_MsoNormal"><span style=3D"font-size:12.0pt; font-family:"= ;Courier New"; color:black"> {</span><span style=3D"font-= size:12.0pt; color:black"></span></p> </div> <div> <p class=3D"x_MsoNormal"><span style=3D"font-size:12.0pt; font-family:"= ;Courier New"; color:black"> void Draw();</= span><span style=3D"font-size:12.0pt; color:black"></span></p> </div> <div> <p class=3D"x_MsoNormal"><span style=3D"font-size:12.0pt; color:black">&nbs= p;</span></p> </div> <div> <p class=3D"x_MsoNormal"><span style=3D"font-size:12.0pt; font-family:"= ;Courier New"; color:black"> double Area { = get; }</span><span style=3D"font-size:12.0pt; color:black"></span></p> </div> <div> <p class=3D"x_MsoNormal"><span style=3D"font-size:12.0pt; color:black">&nbs= p;</span></p> </div> <div> <p class=3D"x_MsoNormal"><span style=3D"font-size:12.0pt; font-family:"= ;Courier New"; color:black"> ShapeType Type= { get; }</span><span style=3D"font-size:12.0pt; color:black"></span></p> </div> <div> <p class=3D"x_MsoNormal"><span style=3D"font-size:12.0pt; font-family:"= ;Courier New"; color:black"> }</span><span style=3D"font-= size:12.0pt; color:black"></span></p> </div> <div> <p class=3D"x_MsoNormal"><span style=3D"font-size:12.0pt; color:black">&nbs= p;</span></p> </div> <div> <p class=3D"x_MsoNormal"><span style=3D"font-size:12.0pt; font-family:"= ;Courier New"; color:black"> public class Square : IShape= </span><span style=3D"font-size:12.0pt; color:black"></span></p> </div> <div> <p class=3D"x_MsoNormal"><span style=3D"font-size:12.0pt; font-family:"= ;Courier New"; color:black"> {</span><span style=3D"font-= size:12.0pt; color:black"></span></p> </div> <div> <p class=3D"x_MsoNormal"><span style=3D"font-size:12.0pt; font-family:"= ;Courier New"; color:black"> public double = Length { get; }</span><span style=3D"font-size:12.0pt; color:black"></span>= </p> </div> <div> <p class=3D"x_MsoNormal"><span style=3D"font-size:12.0pt; font-family:"= ;Courier New"; color:black"> public Square(= double length)</span><span style=3D"font-size:12.0pt; color:black"></span><= /p> </div> <div> <p class=3D"x_MsoNormal"><span style=3D"font-size:12.0pt; font-family:"= ;Courier New"; color:black"> {</span><span = style=3D"font-size:12.0pt; color:black"></span></p> </div> <div> <p class=3D"x_MsoNormal"><span style=3D"font-size:12.0pt; font-family:"= ;Courier New"; color:black"> = Length =3D length;</span><span style=3D"font-size:12.0pt; color:black"></sp= an></p> </div> <div> <p class=3D"x_MsoNormal"><span style=3D"font-size:12.0pt; font-family:"= ;Courier New"; color:black"> }</span><span = style=3D"font-size:12.0pt; color:black"></span></p> </div> <div> <p class=3D"x_MsoNormal"><span style=3D"font-size:12.0pt; color:black">&nbs= p;</span></p> </div> <div> <p class=3D"x_MsoNormal"><span style=3D"font-size:12.0pt; font-family:"= ;Courier New"; color:black"> public void Dr= aw() {}</span><span style=3D"font-size:12.0pt; color:black"></span></p> </div> <div> <p class=3D"x_MsoNormal"><span style=3D"font-size:12.0pt; font-family:"= ;Courier New"; color:black"> public double = Area { get { return Length * Length; } }</span><span style=3D"font-size:12.= 0pt; color:black"></span></p> </div> <div> <p class=3D"x_MsoNormal"><span style=3D"font-size:12.0pt; font-family:"= ;Courier New"; color:black"> public ShapeTy= pe Type { get { return ShapeType.Square; } }</span><span style=3D"font-size= :12.0pt; color:black"></span></p> </div> <div> <p class=3D"x_MsoNormal"><span style=3D"font-size:12.0pt; font-family:"= ;Courier New"; color:black"> }</span><span style=3D"font-= size:12.0pt; color:black"></span></p> </div> <div> <p class=3D"x_MsoNormal"><span style=3D"font-size:12.0pt; color:black">&nbs= p;</span></p> </div> <div> <p class=3D"x_MsoNormal"><span style=3D"font-size:12.0pt; font-family:"= ;Courier New"; color:black"> public class Circle : IShape= </span><span style=3D"font-size:12.0pt; color:black"></span></p> </div> <div> <p class=3D"x_MsoNormal"><span style=3D"font-size:12.0pt; font-family:"= ;Courier New"; color:black"> {</span><span style=3D"font-= size:12.0pt; color:black"></span></p> </div> <div> <p class=3D"x_MsoNormal"><span style=3D"font-size:12.0pt; font-family:"= ;Courier New"; color:black"> public double = Radius { get; }</span><span style=3D"font-size:12.0pt; color:black"></span>= </p> </div> <div> <p class=3D"x_MsoNormal"><span style=3D"font-size:12.0pt; font-family:"= ;Courier New"; color:black"> public Circle(= double radius)</span><span style=3D"font-size:12.0pt; color:black"></span><= /p> </div> <div> <p class=3D"x_MsoNormal"><span style=3D"font-size:12.0pt; font-family:"= ;Courier New"; color:black"> {</span><span = style=3D"font-size:12.0pt; color:black"></span></p> </div> <div> <p class=3D"x_MsoNormal"><span style=3D"font-size:12.0pt; font-family:"= ;Courier New"; color:black"> = Radius =3D radius;</span><span style=3D"font-size:12.0pt; color:black"></sp= an></p> </div> <div> <p class=3D"x_MsoNormal"><span style=3D"font-size:12.0pt; font-family:"= ;Courier New"; color:black"> }</span><span = style=3D"font-size:12.0pt; color:black"></span></p> </div> <div> <p class=3D"x_MsoNormal"><span style=3D"font-size:12.0pt; color:black">&nbs= p;</span></p> </div> <div> <p class=3D"x_MsoNormal"><span style=3D"font-size:12.0pt; font-family:"= ;Courier New"; color:black"> public void Dr= aw() {}</span><span style=3D"font-size:12.0pt; color:black"></span></p> </div> <div> <p class=3D"x_MsoNormal"><span style=3D"font-size:12.0pt; font-family:"= ;Courier New"; color:black"> public double = Area { get { return Math.PI * Radius * Radius; } }</span><span style=3D"fon= t-size:12.0pt; color:black"></span></p> </div> <div> <p class=3D"x_MsoNormal"><span style=3D"font-size:12.0pt; font-family:"= ;Courier New"; color:black"> public ShapeTy= pe Type { get { return ShapeType.Circle; } }</span><span style=3D"font-size= :12.0pt; color:black"></span></p> </div> <div> <p class=3D"x_MsoNormal"><span style=3D"font-size:12.0pt; font-family:"= ;Courier New"; color:black"> }</span><span style=3D"font-= size:12.0pt; color:black"></span></p> </div> <div> <p class=3D"x_MsoNormal"><span style=3D"font-size:12.0pt; color:black">&nbs= p;</span></p> </div> <div> <p class=3D"x_MsoNormal"><span style=3D"font-size:12.0pt; font-family:"= ;Courier New"; color:black"> public class ShapeDataModel<= /span><span style=3D"font-size:12.0pt; color:black"></span></p> </div> <div> <p class=3D"x_MsoNormal"><span style=3D"font-size:12.0pt; font-family:"= ;Courier New"; color:black"> {</span><span style=3D"font-= size:12.0pt; color:black"></span></p> </div> <div> <p class=3D"x_MsoNormal"><span style=3D"font-size:12.0pt; font-family:"= ;Courier New"; color:black"> private Dictio= nary<int, IShape> _shapes =3D new Dictionary<int, IShape>();</s= pan><span style=3D"font-size:12.0pt; color:black"></span></p> </div> <div> <p class=3D"x_MsoNormal"><span style=3D"font-size:12.0pt; font-family:"= ;Courier New"; color:black"> private int _n= extId =3D 1;</span><span style=3D"font-size:12.0pt; color:black"></span></p= > </div> <div> <p class=3D"x_MsoNormal"><span style=3D"font-size:12.0pt; color:black">&nbs= p;</span></p> </div> <div> <p class=3D"x_MsoNormal"><span style=3D"font-size:12.0pt; font-family:"= ;Courier New"; color:black"> public int Add= Shape(IShape shape)</span><span style=3D"font-size:12.0pt; color:black"></s= pan></p> </div> <div> <p class=3D"x_MsoNormal"><span style=3D"font-size:12.0pt; font-family:"= ;Courier New"; color:black"> {</span><span = style=3D"font-size:12.0pt; color:black"></span></p> </div> <div> <p class=3D"x_MsoNormal"><span style=3D"font-size:12.0pt; font-family:"= ;Courier New"; color:black"> = int id =3D _nextId;</span><span style=3D"font-size:12.0pt; color:black"></s= pan></p> </div> <div> <p class=3D"x_MsoNormal"><span style=3D"font-size:12.0pt; font-family:"= ;Courier New"; color:black"> = _shapes[id] =3D shape;</span><span style=3D"font-size:12.0pt; color:black">= </span></p> </div> <div> <p class=3D"x_MsoNormal"><span style=3D"font-size:12.0pt; font-family:"= ;Courier New"; color:black"> = _nextId++;</span><span style=3D"font-size:12.0pt; color:black"></span></p> </div> <div> <p class=3D"x_MsoNormal"><span style=3D"font-size:12.0pt; font-family:"= ;Courier New"; color:black"> = return id;</span><span style=3D"font-size:12.0pt; color:black"></span></p> </div> <div> <p class=3D"x_MsoNormal"><span style=3D"font-size:12.0pt; font-family:"= ;Courier New"; color:black"> }</span><span = style=3D"font-size:12.0pt; color:black"></span></p> </div> <div> <p class=3D"x_MsoNormal"><span style=3D"font-size:12.0pt; color:black">&nbs= p;</span></p> </div> <div> <p class=3D"x_MsoNormal"><span style=3D"font-size:12.0pt; font-family:"= ;Courier New"; color:black"> public IShape = GetShape(int id)</span><span style=3D"font-size:12.0pt; color:black"></span= ></p> </div> <div> <p class=3D"x_MsoNormal"><span style=3D"font-size:12.0pt; font-family:"= ;Courier New"; color:black"> {</span><span = style=3D"font-size:12.0pt; color:black"></span></p> </div> <div> <p class=3D"x_MsoNormal"><span style=3D"font-size:12.0pt; font-family:"= ;Courier New"; color:black"> = return _shapes[id];</span><span style=3D"font-size:12.0pt; color:black"></s= pan></p> </div> <div> <p class=3D"x_MsoNormal"><span style=3D"font-size:12.0pt; font-family:"= ;Courier New"; color:black"> }</span><span = style=3D"font-size:12.0pt; color:black"></span></p> </div> <div> <p class=3D"x_MsoNormal"><span style=3D"font-size:12.0pt; font-family:"= ;Courier New"; color:black"> }</span><span style=3D"font-= size:12.0pt; color:black"></span></p> </div> <div> <p class=3D"x_MsoNormal"><span style=3D"font-size:12.0pt; font-family:"= ;Courier New"; color:black">}</span><span style=3D"font-size:12.0pt; c= olor:black"></span></p> </div> <p class=3D"x_MsoNormal"><span style=3D"font-size:12.0pt; color:black">&nbs= p;</span></p> </div> <div> <p class=3D"x_MsoNormal"><span style=3D"font-size:12.0pt; color:black">&nbs= p;</span></p> </div> <div> <p class=3D"x_MsoNormal"><span style=3D"font-size:12.0pt; color:black; back= ground:#181A1B">**** Python code ****</span><span style=3D"font-size:12.0pt= ; color:black"></span></p> </div> <div> <p class=3D"x_MsoNormal"><span style=3D"font-size:12.0pt; font-family:"= ;Courier New"; color:black; background:#131516">>>> import cl= r</span><span style=3D"font-size:12.0pt; color:black"></span></p> </div> <div> <p class=3D"x_MsoNormal"><span style=3D"font-size:12.0pt; font-family:"= ;Courier New"; color:black; background:#131516">>>> clr.AddRe= ference("Example1")</span><span style=3D"font-size:12.0pt; color:= black"></span></p> </div> <div> <p class=3D"x_MsoNormal"><span style=3D"font-size:12.0pt; font-family:"= ;Courier New"; color:black; background:#131516">>>> import Ex= ample1</span><span style=3D"font-size:12.0pt; color:black"></span></p> </div> <div> <div> <p class=3D"x_MsoNormal"><span style=3D"font-size:12.0pt; font-family:"= ;Courier New"; color:black; background:#131516">>>> sq1 =3D E= xample1.Square(2.)</span><span style=3D"font-size:12.0pt; color:black; back= ground:#131516"></span></p> </div> <div> <p class=3D"x_MsoNormal"><span style=3D"font-size:12.0pt; font-family:"= ;Courier New"; color:black; background:#131516">>>> ci1 =3D E= xample1.Circle(1.3)</span><span style=3D"font-size:12.0pt; color:black; bac= kground:#131516"></span></p> </div> <div> <p class=3D"x_MsoNormal"><span style=3D"font-size:12.0pt; font-family:"= ;Courier New"; color:black; background:#131516">>>> sq2 =3D E= xample1.Square(2.5)</span><span style=3D"font-size:12.0pt; color:black; bac= kground:#131516"></span></p> </div> <div> <p class=3D"x_MsoNormal"><span style=3D"font-size:12.0pt; font-family:"= ;Courier New"; color:black; background:#131516">>>> m =3D Exa= mple1.ShapeDataModel()</span><span style=3D"font-size:12.0pt; color:black; = background:#131516"></span></p> </div> <div> <p class=3D"x_MsoNormal"><span style=3D"font-size:12.0pt; font-family:"= ;Courier New"; color:black; background:#131516">>>> m.AddShap= e(sq1)</span><span style=3D"font-size:12.0pt; color:black; background:#1315= 16"></span></p> </div> <div> <p class=3D"x_MsoNormal"><span style=3D"font-size:12.0pt; font-family:"= ;Courier New"; color:black; background:#131516">1</span><span style=3D= "font-size:12.0pt; color:black; background:#131516"></span></p> </div> <div> <p class=3D"x_MsoNormal"><span style=3D"font-size:12.0pt; font-family:"= ;Courier New"; color:black; background:#131516">>>> m.AddShap= e(sq2)</span><span style=3D"font-size:12.0pt; color:black; background:#1315= 16"></span></p> </div> <div> <p class=3D"x_MsoNormal"><span style=3D"font-size:12.0pt; font-family:"= ;Courier New"; color:black; background:#131516">2</span><span style=3D= "font-size:12.0pt; color:black; background:#131516"></span></p> </div> <div> <p class=3D"x_MsoNormal"><span style=3D"font-size:12.0pt; font-family:"= ;Courier New"; color:black; background:#131516">>>> m.AddShap= e(ci1)</span><span style=3D"font-size:12.0pt; color:black; background:#1315= 16"></span></p> </div> <div> <p class=3D"x_MsoNormal"><span style=3D"font-size:12.0pt; font-family:"= ;Courier New"; color:black; background:#131516">3</span><span style=3D= "font-size:12.0pt; color:black; background:#131516"></span></p> </div> <div> <p class=3D"x_MsoNormal"><span style=3D"font-size:12.0pt; font-family:"= ;Courier New"; color:black; background:#131516">>>> m.GetShap= e(2)</span><span style=3D"font-size:12.0pt; color:black; background:#131516= "></span></p> </div> <div> <p class=3D"x_MsoNormal"><span style=3D"font-size:12.0pt; font-family:"= ;Courier New"; color:black; background:#131516"><Example1.IShape ob= ject at 0x000002A3448A09A0></span><span style=3D"font-size:12.0pt; color= :black; background:#131516"></span></p> </div> <div> <p class=3D"x_MsoNormal"><span style=3D"font-size:12.0pt; font-family:"= ;Courier New"; color:black; background:#131516">>>> m.GetShap= e(2).Area</span><span style=3D"font-size:12.0pt; color:black; background:#1= 31516"></span></p> </div> <div> <p class=3D"x_MsoNormal"><span style=3D"font-size:12.0pt; font-family:"= ;Courier New"; color:black; background:#131516">6.25</span><span style= =3D"font-size:12.0pt; color:black; background:#131516"></span></p> </div> <div> <p class=3D"x_MsoNormal"><span style=3D"font-size:12.0pt; font-family:"= ;Courier New"; color:black; background:#131516">>>> m.GetShap= e(2).Length</span><span style=3D"font-size:12.0pt; color:black; background:= #131516"></span></p> </div> <div> <p class=3D"x_MsoNormal"><span style=3D"font-size:12.0pt; font-family:"= ;Courier New"; color:black; background:#131516">Traceback (most recent= call last):</span><span style=3D"font-size:12.0pt; color:black; background= :#131516"></span></p> </div> <div> <p class=3D"x_MsoNormal"><span style=3D"font-size:12.0pt; font-family:"= ;Courier New"; color:#ED5C57; background:#131516"> File "&l= t;stdin>", line 1, in <module></span><span style=3D"font-size= :12.0pt; color:black; background:#131516"></span></p> </div> <div> <p class=3D"x_MsoNormal"><span style=3D"font-size:12.0pt; font-family:"= ;Courier New"; color:#ED5C57; background:#131516">AttributeError: 'ISh= ape' object has no attribute 'Length'</span><span style=3D"font-size:12.0pt= ; color:black; background:#131516"></span></p> </div> </div> <div> <p class=3D"x_MsoNormal"><span style=3D"font-size:12.0pt; color:black; back= ground:#131516"><br> <br> </span><span style=3D"font-size:12.0pt; color:black"></span></p> </div> <div> <p class=3D"x_MsoNormal"><span style=3D"font-size:12.0pt; color:black; back= ground:#131516">**** summary ****</span><span style=3D"font-size:12.0pt; co= lor:black"></span></p> </div> <div> <p class=3D"x_MsoNormal"><span style=3D"font-size:12.0pt; color:black; back= ground:#131516">This factory and/or datamodel pattern is very common in my = codebase and probably also lots of object oriented systems. The menti= oned PR breaks this common design pattern in C# objects wrapped by pythonnet, and I would like a way to opt-out of i= t. Maybe an attribute on the method which returns an interface can be= used, or maybe something global to switch this behavior. I think per= haps the original bug might also have been fixed in a different way. </span><span style=3D"font-size:12.0pt; col= or:black"></span></p> </div> <div> <p class=3D"x_MsoNormal"><span style=3D"font-size:12.0pt; color:black; back= ground:#131516"><br> <br> </span><span style=3D"font-size:12.0pt; color:black"></span></p> </div> <p class=3D"x_MsoNormal"><span style=3D"font-size:12.0pt; color:black; back= ground:#131516">Thanks!<br> Mohamed</span><span style=3D"font-size:12.0pt; color:black"></span></p> <p class=3D"x_MsoNormal"> </p> </div> </div> </div> </body> </html> --_000_SN6PR01MB4976CCEE1E29E0FC89CE0CC8998F9SN6PR01MB4976prod_-- --===============4369368159843712820== Content-Type: text/plain; charset="us-ascii" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Content-Disposition: inline _______________________________________________ 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] --===============4369368159843712820==--