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:
TestServiceInterface.cs
using System;
using System.ServiceModel;
namespace TestServiceInterface
{
[ServiceContract]
public interface ImyService
{
[OperationContract]
string GetData(int value);
}
}TestService.cs
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("Press to 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:
TestService.py
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("Press to 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:
TestClient.cs
using System;
using System.ServiceModel;
using TestServiceInterface;
namespace myWcfClient
{
public class cli
{
public static void Main()
{
ChannelFactory mycf = 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));
}
}
}
TestClient.py
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.
Note: If you see closing tags (e.g. enter or ImyService) at the end of listings, it looks like SyntaxHighlighter bug in Google Chrome...

0 comments:
Post a Comment