El 27/09/2011, a las 16:54, Keith Rome escribió: > Just beware that if you use this same mechanism to introspect CLR objects, it > can return member names for static and protected members in addition to the > public instance members (and attempts to access those members might fail). To > work around this, I first use reflection to get a list of static or protected > CLR members and then exclude those member names from the list returned by > Operations.GetMemberNames(). For Python objects, this doesn't seem to cause > any complications, since reflection does not know anything about the dynamic > members.
My use case is pure Python objects, and right now a couple of C# lines solved it. > > Doing it that way allows the same code to operate correctly in a > heterogeneous environment, where some objects might originate from a dynamic > scope while others originate from a static managed scope. Interesting. I might use it in case our users decided to extend our application by using IP and pure .NET dlls. So far nobody did that, but who knows.... Thanks again, -Hernán. > > Example (I am sure there are ways to tighten this up, but it gets the job > done): > > IEnumerable<string> GetMemberNames(dynamic obj) > { > // use reflection first so we can exclude anything that will just fail > under the dynamic context > var objType = ((object)obj).GetType(); > var staticMembers = objType.GetMembers(BindingFlags.FlattenHierarchy | > BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic); > var privateMembers = objType.GetMembers(BindingFlags.Instance | > BindingFlags.NonPublic); > var excludedMembers = staticMembers.Union(privateMembers).Select(member => > member.Name).OrderBy(name => name).Distinct(); > > var langContext = > HostingHelpers.GetLanguageContext(_scriptService.GetScriptEngine()); > try > { > IList<string> members; > > try > { > members = langContext.Operations.GetMemberNames(obj); > } > catch (AmbiguousMatchException) > { > members = langContext.Operations.GetMemberNames((object)obj); > } > > members = members.Except(excludedMembers).ToList(); > > // ... I do some more work here to filter out members that start with > underbar > // character or that resolve to types that don't make sense for my > purposes (events, etc) > > return members; > } > catch (Exception) > { > return new string[] { }; > } > } > > > Keith Rome > Senior Consultant and Architect > MCPD-EAD, MCSD, MCDBA, MCTS-WPF, MCTS-TFS, MCTS-WSS > Wintellect | 770.617.4016 | kr...@wintellect.com > www.wintellect.com > > > -----Original Message----- > From: ironpython-users-bounces+rome=wintellect....@python.org > [mailto:ironpython-users-bounces+rome=wintellect....@python.org] On Behalf Of > Hernán Foffani > Sent: Tuesday, September 27, 2011 6:43 AM > Cc: ironpython-users@python.org > Subject: Re: [Ironpython-users] instropection in an embedded engine > > You are right. It was the all the Operations thing what I was missing > altogether, silly me. > Now it all make sense. > Thanks a lot. > > El 26/09/2011, a las 19:57, Keith Rome escribió: > >> If you are just trying to enumerate members of a python object, and possibly >> invoke them, then wouldn't a LanguageContext's DynamicOperations get the job >> done? Perhaps I am misunderstanding your objectives though. >> >> HostingHelpers.GetLanguageContext(ScriptEngine) to get the LanguageContext, >> and then just use the Operations property from that. This gives you >> introspection methods for GetMemberNames() and a number of invocation >> mechanisms. All you need is a reference to an object to inspect and the >> language engine that owns it (or one that is compatible with it). >> >> In my implementation of a Watches/Locals/Modules UI for a python debugger, I >> use that procedure as the basis for routines that populate the inspector >> grids. Basically, whenever the user reaches a breakpoint via my settrace() >> hook, I inspect the members of all variables in the current scope and >> refresh a visual tree (really a grid with indentation), and as they drill >> down into those objects I just walk down one step further into the data >> structure. It isn't the fastest thing in the world, but then again it >> doesn't have to be - the script is effectively paused until I allow the >> breakpoint to resume. >> >> >> Keith Rome >> Senior Consultant and Architect >> MCPD-EAD, MCSD, MCDBA, MCTS-WPF, MCTS-TFS, MCTS-WSS Wintellect | >> 770.617.4016 | kr...@wintellect.com www.wintellect.com >> >> >> -----Original Message----- >> From: ironpython-users-bounces+rome=wintellect....@python.org >> [mailto:ironpython-users-bounces+rome=wintellect....@python.org] On >> Behalf Of Hernán Foffani >> Sent: Monday, September 26, 2011 1:36 PM >> To: ironpython-users@python.org >> Subject: Re: [Ironpython-users] instropection in an embedded engine >> >> Thanks, I'm getting closer. >> Now I'm trying to find how to get a (new? current?) CodeContext to, for >> instance, call DictProxy.keys(..) The public constructor of CodeContext >> signature (a PythonDictionary and a ModuleContext) doesn't match the >> examples I could find (ScriptScope, LanguageContext). >> >> Does anyone know of any examples of introspection of a hosted IP scripting >> from C#? >> Evidently there's a lot I'm missing here and would like to do the due >> homework first. >> >> I'm using NET 4 and don't need 2.x compatibility. >> >> Regards, >> -Hernán >> >> El 23/09/2011, a las 21:43, Dino Viehland escribió: >> >>> __class__ exists on object in python and is then inherited by the >>> other types. When accessing a member from C# you get its view of the world >>> which doesn't include Python object members. To get the Python type I >>> suggest calling DynamicHelpers.GetPythonType. >>> >>> Sent from my Windows Phone >>> >>> -----Original Message----- >>> From: Hernán Foffani >>> Sent: Friday, September 23, 2011 9:12 AM >>> To: ironpython-users@python.org >>> Subject: [Ironpython-users] instropection in an embedded engine >>> >>> >>> Having the following Python code: >>> >>> class Plugin: >>> def method(self): >>> pass >>> plugin = Plugin() >>> >>> and an embedded ScriptScope instance in my .NET application, the >>> following C# works fine >>> >>> dynamic plugin = pythonEngine.GetVariable("plugin"); >>> var attrs = plugin.__class__.__dict__; >>> >>> if Plugin python class was defined as an old-style class, but fails >>> if Plugin inherits from object (__class__ non existent). >>> >>> Under the VS debugger the dynamic object plugin shows as having three >>> attributes .class, .dict and .slots_and_weakref (with dots in their >>> names) but no __class__ or __dict__. >>> >>> I found that I could do something like >>> plugin.method.im_class.__dict__ but I'd rather stick with the common idiom. >>> >>> Is it a known issue? Something related to the way I'm using the engine? >>> >>> Thanks in advance, >>> -Hernán. >>> >>> _______________________________________________ >>> Ironpython-users mailing list >>> Ironpython-users@python.org >>> http://mail.python.org/mailman/listinfo/ironpython-users >>> >> >> _______________________________________________ >> Ironpython-users mailing list >> Ironpython-users@python.org >> http://mail.python.org/mailman/listinfo/ironpython-users >> >> > > _______________________________________________ > Ironpython-users mailing list > Ironpython-users@python.org > http://mail.python.org/mailman/listinfo/ironpython-users > > _______________________________________________ Ironpython-users mailing list Ironpython-users@python.org http://mail.python.org/mailman/listinfo/ironpython-users