[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

JCSP Advice anyone?



I'm new to using JCSP, and thought this might be a good place to ask for help. If I was wrong in that thought, please forgive me...


What I want to know is am I on the "right track", or is there a better way?


I'm using JCSP in a Visual Studio 2005 / .NET 2.0 project in which the majority of the logic will be written as simple classes. Among the reasons:


 - it makes it easier and clearer, as the process logic is distinct from business logic;


 - it makes it easier to test; I can use the built-in VS2005 NUnit test tools;


 - while interoperability between J# and C# is good it isn't perfect (e.g. J# "objects" are not the same as C# "objects" for some reason).


So, I've ended up with a set of native C# and VB.NET classes that implement the basic code of the system. However, the design requires that several of the classes exist in their own process. Knowing about JCSP I thought it would be a good tool to use.


What I'm starting to do is set up wrapper classes that implement the translation of method and property arguments into an object request and response pairs, and a Server process that implements CSProcess and processes requests.


Sounds all right so far?


So at the client end we get an object constructor like:


    public Client(ChannelOutput req, ChannelInput resp)


        mReq = req;

        mResp = resp;



And methods, etc, like:


    public bool IsLoggedIn


        get {

            ServiceReq req = new ServiceReq(ServiceReqCode.IsLoggedIn);


            ServiceReply reply = (ServiceReply)mResp.read();

            return reply.code == ServiceRespCode.Success && reply.resp3;




And at the server end something like:


    private AltingChannelInput[] mInputs;

    private ChannelOutput[] mOutputs;


    public Server(string servername, AltingChannelInput[] svrin, ChannelOutput[] svrout)


        mSecurityManager = new Stuga.General.SecurityManager(mDatabase, false);

        mInputs = svrin;

        mOutputs = svrout;




And a run() that does:


    while (running)


        int index = alt.fairSelect ();

        object obj = mInputs[index].read();


        if (obj.GetType() != typeof(ServiceReq))

            continue;           // someone sent the wrong thing to us!


        ServiceReq req = (ServiceReq)obj;

        switch (req.code)


            case ServiceReqCode.IsLoggedIn:

                try {

                    mOutputs[index].write(new ServiceReply(ServiceRespCode.Success, mSecurityManager.IsLoggedIn));


                catch (Stuga.General.LoginException le){

                    mOutputs[index].write(new ServiceReply(ServiceRespCode.Exception, le.Message));







Lastly, the objects being sent around look like this:


        public enum ServiceReqCode


            IsLoggedIn,         // () -> (resp3)

            IsOperatorKnown,    // (arg2) -> (resp3)



        public enum ServiceRespCode






        public class ServiceReq


            public ServiceReq() {}

            public ServiceReq(ServiceReqCode c, string a1)


                code = c;

                arg1 = a1;


            public ServiceReq(ServiceReqCode c, long a2)


                code = c;

                arg2 = a2;



            public ServiceReqCode code;

            public string arg1;

            public long arg2;

            public Stuga.General.LoginAction arg3;



And similarly for the response object.


I've named the object values generically (arg1 etc) because they're reused for different things depending on the method call. The downside about this is that there are usually several different data types used per class, and I'm very tempted to use some kind of dictionary collection, and have named objects instead. I really want to keep to one type of object per server.


Am I mad yet?