Edit 17. 11. 2009: See the article about WCF service in pure IronPython.
Until IronPython 2.6, it was not possible to create WCF service host in pure IronPython. The closest way was to create stub in C# and subclass it in IronPython or create the whole service in C# and run it from IronPython. It is now much simpler with IronPython 2.6 although you still have to write a little C# code.
Simple WCF service implemented in C# looks like this:
using System; using System.ServiceModel; namespace TestServiceInterface { [ServiceContract] public interface ImyService { [OperationContract] string GetData(int value); } }
using System; using System.ServiceModel; using TestServiceInterface; namespace myWcfService { public class myService : ImyService { public string GetData(int value) { return string.Format("You entered: {0}", value); } } public class mySvc { public static void Main() { ServiceHost sh = new ServiceHost( typeof(myService), new Uri("http://localhost:9000/myWcfService")); sh.AddServiceEndpoint( typeof(ImyService), new BasicHttpBinding(), ""); sh.Open(); Console.WriteLine("Pressto terminate\n"); Console.ReadLine(); sh.Close(); } } }
You build it:
csc /target:library TestServiceInterface.cs csc /r:TestServiceInterface.dll TestService.cs
The reason I put TestServiceInterface into separate file is that you cannot create interfaces in IronPython. So this is the only part written in C# when implementig WCF service in IronPython.
The implementation then looks like this:
import clr import clrtype clr.AddReference('System.ServiceModel') clr.AddReference('TestServiceInterface') from TestServiceInterface import ImyService from System import Console, Uri from System.ServiceModel import (ServiceHost, BasicHttpBinding, ServiceBehaviorAttribute, InstanceContextMode) ServiceBehavior = clrtype.attribute(ServiceBehaviorAttribute) class myService(ImyService): __metaclass__ = clrtype.ClrMetaclass _clrnamespace = "myWcfService" _clrclassattribs = [ ServiceBehavior(InstanceContextMode=InstanceContextMode.Single)] def GetData(self, value): return "IronPython: You entered: %s" % value sh = ServiceHost( myService(), Uri("http://localhost:9000/myWcfService") ) sh.AddServiceEndpoint( clr.GetClrType(ImyService), BasicHttpBinding(), "") sh.Open() Console.WriteLine("Pressto terminate\n") Console.ReadLine() sh.Close()
The myService class must have InstanceContextMode.Single ServiceBehavior attribute because we are passing service instance to the ServiceHost constructor. This is done via new __clrtype__ metaclass. See the error if we don't use the attribute. I was not able to pass type into the ServiceHost constructor.
To test the service, you can use C# or IronPython client implementation:
using System; using System.ServiceModel; using TestServiceInterface; namespace myWcfClient { public class cli { public static void Main() { ChannelFactorymycf = new ChannelFactory ( new BasicHttpBinding(), new EndpointAddress("http://localhost:9000/myWcfService")); ImyService wcfcli = mycf.CreateChannel(); Console.WriteLine("Calling GetData(33) returns:\n{0}", wcfcli.GetData(33)); } } }
import clr clr.AddReference('System.ServiceModel') import System.ServiceModel clr.AddReference('TestServiceInterface') from TestServiceInterface import ImyService mycf = System.ServiceModel.ChannelFactory[ImyService]( System.ServiceModel.BasicHttpBinding(), System.ServiceModel.EndpointAddress("http://localhost:9000/myWcfService")) wcfcli = mycf.CreateChannel() print "WCF service returned:\n%s" % wcfcli.GetData(11)
Disadvantages:
- You can have only single instance of the service because you are passing the service instance instead of service type.
- You cannot easily use .config file to configure your service.