Jimmy Schementi wrote:
> I’m actually using this stuff in a talk next month, so I guess *someone*
> has to get it working. =P Christian , if you are working on this, by all
> means continue, otherwise when I make progress I’ll let you know
>

Fair enough! :)

Well, I had a go at doing this in the weekend, and after a bit of mucking around implementing GetCustomMember and Call methods, I realised that all I really need is the WsdlProvider part. And then that a lot of the stuff the WsdlProvider is doing (adding properties to the code dom for the to-be-generated assembly to enable access to types defined in the WSDL) is much easier done in Python than in C#.

So I did that instead. The interface is different - something like this:

>>> import wsdlprovider as wsdl
>>> url = 'http://www.dotnetjunkies.com/quickstart/aspplus/samples/services/MathService/VB/MathService.asmx'
>>> math = wsdl.GetWebServiceAssembly(url)
>>> ws = math.MathService()
>>> ws.Add(40, 2.5)
42.5

It turned out that modifying the CodeDom wasn't really necessary - if you return the assembly instead of the proxy type, you can just treat it as a module, and the constructors for parameters to service methods are available already. And if you don't already know the name of the proxy type, you can use wsdlprovider.FindProxyType, which rummages through the assembly to find something that inherits from SoapHttpClientProtocol.

It doesn't unify the interfaces as much as they were in the C# code, but that's not that important for the stuff I'm writing.

There were a couple of questions that occurred to me when I was doing it in C# (before I remembered that I'd rather code in Python).

* While I can replace attribute injectors with GetCustomMember and friends in classes that I'm defining (like WebServiceHelper), DynamicWebServiceHelpers also registers injectors for string (for pluralisation) and XmlElement (convenient child element access). This is a bit like C#'s extension methods (or if I'm feeling uncharitable, Ruby class monkeypatching, since I don't think it's namespaced). How would I get this effect (particularly for the SimpleXmlHelper stuff) in IP2? (Although given the rubyesqueness, maybe I wouldn't want it! ;)

In Python, I guess I'd create a transparent wrapper for XmlElement that delegates from __getattr__ (for real XmlElement attributes) and then falls back to the cleverness allowing named child element access. But that wouldn't automatically affect every XmlElement - I'd have to manually wrap any elements as I returned them from my wrapper.

* The properties that WsdlProvider adds to the CodeDom before generating an assembly are implemented using a call to Ops.GetDynamicTypeFromType. I couldn't work out the corresponding call in IP2. How would I do that?


I haven't tried to port the SimpleXmlHelper and pluralisation to Python yet - it's less useful to me.

Not sure what the focus of your talk is, Jimmy, but hopefully this is some help?

Cheers,
Christian

~js

On 5/9/08 8:46 AM, "Dino Viehland" <[EMAIL PROTECTED]> wrote:

    And ICallable is the same - you can now mark a method w/ SpecialName
    and call it "Call" and it'll be invoked when you're calling the
    object.  You can even have multiple overloads, all strongly typed,
    etc...

    -----Original Message-----
    From: [EMAIL PROTECTED]
    [mailto:[EMAIL PROTECTED] On Behalf Of Sanghyeon Seo
    Sent: Friday, May 09, 2008 6:39 AM
    To: Discussion of IronPython
    Subject: Re: [IronPython] Updating WebServices samples

    2008/5/9 Christian Muirhead <[EMAIL PROTECTED]>:
    >  Is there any chance that someone has updated these to work with
    the IP2
    >  architecture? If not, how much work would people expect it to be?
    The errors
    >  I saw when I quickly tried to compile the C# were primarily about
    not being
    >  able to find the IAttributesInjector and ICallable interfaces - do
    these
    >  exist in the same form in the new architecture?

    I think IAttributesInjector -- which was hacky, IMO -- has been
    replaced by defining GetBoundMember method and marking the method with
    SpecialNameAttribute.

    Details are here:
    
http://blogs.msdn.com/srivatsn/archive/2008/04/12/turning-your-net-object-models-dynamic-for-ironpython.aspx

    --
    Seo Sanghyeon
    _______________________________________________
    Users mailing list
    [email protected]
    http://lists.ironpython.com/listinfo.cgi/users-ironpython.com

    _______________________________________________
    Users mailing list
    [email protected]
    http://lists.ironpython.com/listinfo.cgi/users-ironpython.com


------------------------------------------------------------------------

_______________________________________________
Users mailing list
[email protected]
http://lists.ironpython.com/listinfo.cgi/users-ironpython.com


--
Christian Muirhead
Senior Developer
Resolver Systems
[EMAIL PROTECTED]
We're hiring! http://www.resolversystems.com/jobs/


Resolver Systems Ltd
17a Clerkenwell Road, London EC1M 5RD, UK
VAT No.: GB 893 5643 79 Registered in England and Wales as company number 5467329.
Registered address: 843 Finchley Road, London NW11 8NA, UK
import clr

clr.AddReference("System.Web.Services")
clr.AddReference("System.Xml")


from System.Web.Services.Description import (
    ServiceDescription, ServiceDescriptionImporter
)
from System.Web.Services.Protocols import SoapHttpClientProtocol
from System.IO import MemoryStream
from System.Net import WebClient

from System.CodeDom import (
    CodeCompileUnit, CodeNamespace
)
from System.CodeDom.Compiler import CodeDomProvider, CompilerParameters
from System.Xml.Serialization import CodeGenerationOptions


def CreateServiceAssemblyFromWsdl(wsdl):
    # generate CodeDom from WSDL
    sd = ServiceDescription.Read(MemoryStream(wsdl))
    importer = ServiceDescriptionImporter()
    importer.ServiceDescriptions.Add(sd)

    codeCompileUnit = CodeCompileUnit()
    codeNamespace = CodeNamespace("")
    codeCompileUnit.Namespaces.Add(codeNamespace)
    importer.CodeGenerationOptions = (CodeGenerationOptions.GenerateNewAsync
        | CodeGenerationOptions.GenerateOldAsync)
    importer.Import(codeNamespace, codeCompileUnit)

    # compile CodeDom into an assembly
    provider = CodeDomProvider.CreateProvider("CS")
    compilerParams = CompilerParameters()
    compilerParams.GenerateInMemory = True
    compilerParams.IncludeDebugInformation = False
    results = provider.CompileAssemblyFromDom(compilerParams, codeCompileUnit)
    generatedAssembly = results.CompiledAssembly

    return generatedAssembly


def GetWebServiceAssembly(url):
    if url.lower().endswith(".asmx"):
        url += "?WSDL"

    data = WebClient().DownloadData(url)
    return CreateServiceAssemblyFromWsdl(data)


def FindProxyType(assembly):
    for name in dir(assembly):
        item = getattr(assembly, name)
        if type(item) is type and issubclass(item, SoapHttpClientProtocol):
            return item


_______________________________________________
Users mailing list
[email protected]
http://lists.ironpython.com/listinfo.cgi/users-ironpython.com

Reply via email to