I'm designing a client (UI made with WPF) and server (WCF) that communicates with a device known as DDC (Direct Digital Control). A user on the client side can make requests to adjust the state of the DDC, then the server receives the information from the client and invokes appropriate operation on the DDC. DDC uses SOAP protocol for communication so I have a WSDL file that is being imported as service reference in Server, so invoking operations from the Server to DDC is very straight forward.
I'm having some trouble designing a solid data structure and interfaces for communication between UI and Engine, largely because there are a lot of operations defined in the WSDL file that I need to handle (like over 300 operations). Most of them return a string or a list of string, but some of them are defined as structures with a lot of fields.
For my interface, I initially thought about defining operationcontracts based on what parameters/return types some trivial function Require:
[ServiceContract]
public interface IDDCEngine
{
[OperationContract(Name = "GetPointValueSpecific")]
string GetPointValueSpecific(string host, string operation, out List<PointSpecificInformation> pointSpecificInfoList);
[OperationContract(Name = "GetPointValueCommon")]
string GetPointValueCommon(string host, string operation, out List<PointCommonInformation> pointCommonInfoList);
[OperationContract(Name = "SetPointValueCommon")]
string SetPointValueCommon(string host, string operation, List<PointCommonInformation> pointCommonInfo);
[OperationContract(Name = "SetPointValueSpecific")]
string SetPointValueSpecific(string host, string operation, List<PointSpecificInformation> pointSpecificInfo);
[OperationContract(Name = "SendRequestListMultipleInMultipleOut")]
string SendRequest(string host, string operation, List<string> parameters, out List<string> ddcResponse);
[OperationContract(Name = "SendRequestSingleInMultipleOut")]
string SendRequest(string host, string operation, string parameters, out List<string> ddcResponse);
[OperationContract(Name = "SendRequestMultipleInSingleOut")]
string SendRequest(string host, string operation, List<string> parameters, out string ddcResponse);
[OperationContract(Name = "SendRequestSingleInSingleOut")]
string SendRequest(string host, string operation, string parameter, out string ddcResponse);
[OperationContract(Name = "SendRequestSingleOut")]
string SendRequest(string host, string operation, out string ddcResponse);
}
The return type is string to indicate the status connection between UI/Engine (Validate/Error). Out parameter is the relevant response (data) received from DDC.
Here is an example of my engine implementation:
//Parameters: Single
//Response: Multiple
public string SendRequest(string host, string operation, string parameter, out List<string> value)
{
value = new List<string>();
string result = OPERATION_VALIDATE;
try
{
DDCService.LGeDDCClient ddc = new DDCService.LGeDDCClient(DDC_NAMESPACE, host);
switch (operation)
{
case "GetCPUMemoryStatus":
int count;
if (!int.TryParse(parameter, out count))
result = INVALID_PARAMETER;
//Returns in the order of Process/Memory:
string memory;
string process = ddc.GetCPUMemoryStatus(count, out memory);
value.Add(process);
value.Add(memory);
return OPERATION_VALIDATE;
case "GetVersion":
string kernel;
string ramdisk = ddc.GetVersion(out kernel);
value.Add(kernel);
value.Add(ramdisk);
return OPERATION_VALIDATE;
default:
result = UNDEFINED_OPERATION;
return result;
}
}
catch (Exception ex)
{
result = ex.Message;
return result;
}
finally
{
DisplayTransmissionOnTextbox(operation, host, result);
}
}
//Parameters: Multiple
//Response: Single
public string SendRequest(string host, string operation, List<string> parameter, out string value)
{
value = String.Empty;
string result = OPERATION_VALIDATE;
try
{
DDCService.LGeDDCClient ddc = new DDCService.LGeDDCClient(DDC_NAMESPACE, host);
switch (operation)
{
case "RequestUpgrade":
if (parameter.Count != 2)
return INVALID_PARAMETER;
int upgradeTarget;
if (!int.TryParse(parameter[1], out upgradeTarget))
return INVALID_PARAMETER;
value = ddc.RequestUpgrade(parameter[0], upgradeTarget);
return OPERATION_VALIDATE;
default:
value = null;
return UNDEFINED_OPERATION;
}
}
catch (Exception ex)
{
result = ex.Message;
return result;
}
finally
{
DisplayTransmissionOnTextbox(operation, host, result);
}
}
//Parameters: Single
//Response: Single
public string SendRequest(string host, string operation, string parameter, out string value)
{
value = String.Empty;
string result = OPERATION_VALIDATE;
try
{
DDCService.LGeDDCClient ddc = new DDCService.LGeDDCClient(DDC_NAMESPACE,host);
switch (operation)
{
case "EndRestore":
value = ddc.EndRestore(parameter);
return OPERATION_VALIDATE;
case "EndBackup":
value = ddc.EndRestore(parameter);
return OPERATION_VALIDATE;
case "GetLogicSource":
value = ddc.GetLogicSource(parameter);
return OPERATION_VALIDATE;
default:
result = UNDEFINED_OPERATION;
return result;
}
}
catch (Exception ex)
{
result = ex.Message;
return result;
}
finally
{
DisplayTransmissionOnTextbox(operation, host, result);
}
}
//Parameters: None
//Response: Single
public string SendRequest(string host, string operation, out string value)
{
value = String.Empty;
string result = OPERATION_VALIDATE;
try
{
DDCService.LGeDDCClient ddc = new DDCService.LGeDDCClient(DDC_NAMESPACE, host);
switch (operation)
{
case "StartRestore":
value = ddc.StartRestore();
return result;
case "StartBackup":
value = ddc.StartBackup();
return result;
case "RequestReboot":
value = ddc.RequestReboot();
return result;
case "StartUpgrade":
value = ddc.StartUpgrade();
return result;
case "GetDatabaselist":
value = ddc.GetDatabaselist();
return result;
case "GetProcesslist":
value = ddc.GetProcesslist();
return result;
case "GetCurrenttime":
value = ddc.GetCurrenttime();
return result;
case "GetUptime":
value = ddc.GetUptime();
return result;
default:
result = UNDEFINED_OPERATION;
return result;
}
}
catch (Exception ex)
{
result = ex.Message;
return result;
}
finally
{
DisplayTransmissionOnTextbox(operation, host, result);
}
}
Is this really a good approach of designing my interface for Client/Engine? My goal was to minimize the number of interfaces by stuffing many DDC operations, but I feel like what I'm writing is pretty dirty and can lead to problems. I would really appreciate any recommendations that can be made here.