First, this is not a duplicate of IEnumerable<T> as return type for WCF methods, I think I understand that the WCF architecture only allows concrete types to be transferred that can be stuffed into a message.
Second, our setup however is not a general service but connecting up a bundle of proprietary apps via C# + WCF + NetTcpBinding + Protobuf (only) so we may have more room for some tricks that something that needs to be more binding neutral.
Third, it is neither my place nor this question's to propose a different RPC or messaging framework.
"IEnumerable semantics", for the purpose of this question, are:
List
or similar.foreach
and be done with it.In a local assembly, a C# interface my look like this:
interface IStuffProvider {
IEnumerable<Stuff> GetItems(); // may open large file or access database
}
You can't map that directly to a WCF service. Something that might achieve the same could look like:
[ServiceContract(SessionMode = SessionMode.Required)]
interface IStuffService {
[OperationContract]
void Reset(); // may open large file or access database
[OperationContract]
List<Stuff> GetNext(); // return next batch of items (empty list if no more available)
}
Of course, using IStuffService
will be more error prone than a IStuffProvider
and add in to the mix than many usage scenarios would involve using both service and client on the same machine, so for "user code" it wouldn't be super important to be aware that "the network" is involved, the user code is just interested in a simple interface.
One option would be of course to have a client side interface wrapper implementation, that exposes IStuffProvider
and internally forwards to and uses IStuffService
.
However, it seems it would really be desirable to not have to maintain two interfaces, one for user code, one solely for the WCF communication, especially as these applications are all tightly coupled anyway, so the additional abstraction just seems overhead.
What are the options we have here with WCF?
Note that after reading up on it, the Streamed Binding seems a poor solution, as I would still need a wrapper on the client side and the service interface would get more complex for no real gain in my case: I don't need maximum binary transfer efficiency, I would like good implementation + maintenance efficiency.
Some time ago we faced the same WCF "restriction" in our project. To be short, we ended up with
interface IStuffProvider {
List<Stuff> GetItems(int page, int pageSize); // may open large file or access database
}
Yes, it is not the same as IEnumerable<Stuff> GetItems();
Yes, we can get in troubles when some item added/removed on already received page. Yes, it is required some server-side tweaks, if server works with items in terms of IEnumerable<Stuff>
. But it is still strictly typed and does not bring much additional logic in the client or the server.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With