I have an application which will use WCF as the underlying transport mechanism of an app protocol, but this question is more about service orientated design rather than WCF specifically.
I have different data source plugins running on the server which can be referenced by the client calling GetData on the service, and specifying the data source name. Such a function call would return a list of data such as an array of overdue invoices:
class OverdueAccounts
{
float Amount;
int Days;
string Reference;
}
Or an array of open support cases:
class OpenTickets
{
DateTime Date;
Guid TicketId;
TicketStatus Status;
}
Only on loading of plugins would we know the types that will be returned and what data access methods are available.
public interface IDataSourcePlugin /* plugin running on server */
{
string Name;
Type DataType;
object GetDataType(); // returns a type of the type specified above by DataType
}
public interface IAppService /* service contract */
{
[OperationContract]
object GetData(string datasourceName); // will call plugins IDataSourcePlugin.GetDataType
}
My issue is these types will only be known at runtime and I don’t like untyped objects but don’t know of any other recommended way to achieve what I need.
I have thought about transferring the data object by return a string of XML and specifying a DTD to validate, but this adds an extra layer on top of what WCF can do for me already.
Alternatively, I can set up a concrete set of operations such as ReadString(string fieldname), ReadInt(string fieldname) and so forth, but that could mean many calls.
It is important to keep the data flow and messages within the set protocol and all going from client to the server and then the server on to the data source, as opposed to each client going directly to the data source. This is for caching and other business requirement reasons.
Any recommendations on how to structure the transport and structure for types which can only be known at runtime or an alternative design would be great.
You need to add a
ServiceBehaviorwith a customDataContractResolverto the service. In this customDataContractResolveryou can dynamically add your Types and the corresponding names.On the client side you most likely will also have to add a similar contract resolver, so this only works if you know what types you might reveive from the service.
I am using a simple Dictionary in both resolvers.