views:

341

answers:

2

I have an application where client and server share types, and interoperability is not one of our concerns. I am planning to have a single repository for all web enabled objects, and i was thinking of a generic interface for my exposed service.

something like T GetObject(int id)

but wcf doesnt like it since its trying to expose its schema (which i dont really care about)

is it possible to do such a thing with WCF ?, i can use any type of binding doesnt have to be httpbinding or wsbinding...

+2  A: 

No, you can't. Whether or not you want or need interoperability, the most basic foundation of WCF is message exchange.

The client send the server a message and gets back a response. That message is all that passes between client and server, and needs to be serializable into a XML or binary format. That's why any data being passed around must be atomic (like int, string) or a DataContract - a description for the WCF service stack about how to serialize and deserialize such objects.

You cannot pass any interfaces, or other "trickery" - all that goes between client and server must be expressable in XML schema, basically.

So I'm afraid what you're trying to achieve is quite contrary to what WCF offers. The world and paradigms of SOA (Service-Oriented Apps) are quite different and not always 100% in sync with the idea and mechanisms of OOP.

Marc

marc_s
so if someone wanted to do this, what technology stack does MS offer, is it more suitable for remoting ( if thats still alive) ? Ms does extend support for sharing types ( netcontractserializer etc)
I don't know if there's any current solution for remoting objects - which is basically what you're trying to do. This approach does have its share of problems, which MS tries to solve with WCF - but in order to solve it, one has to go to a fully message-based model, which doesn't work well with interfaces and generics. Yes, it support sharing CONCRETE types - but definitely not interfaces, and not really generics.
marc_s
+1  A: 

I suppose this is possible, though I'm not sure you'd want this. I'd take the following approach (untested, not sure if it works). First create the following project structure in your solution:

  • ServiceInterfaces
  • ServiceImplementations (references ServiceInterfaces and ModelClasses)
  • ModelClasses
  • Host (references ServiceInterfaces and ServiceImplementations)
  • Client (references ServiceInterfaces and ModelClasses)

In ServiceInterfaces you have an interface like this (I skipped the namespaces, etc to make the example shorter):

[ServiceContract]
public interface IMyService<T>
{
    T GetObject(int id);
}

In ServiceImplementations you have a class that implements IMyService<T>:

public class MyService<T> : IMyService<T>
{
    T GetObject(int id)
    {
        // Create something of type T and return it. Rather difficult
        // since you only know the type at runtime.
    }
}

In Host you have the correct configuration for your service in an App.config (or Web.config) file and the following code to host your service (given that it is a stand-alone app):

ServiceHost host = new ServiceHost(typeof(MessageManager.MessageManagerService))
host.Open();

And finally in Client you use a ChannelFactory<TChannel> class to define a proxy:

Binding binding = new BasicHttpBinding(); // For the example, could be another binding.
EndpointAddress address = new EndpointAddress("http://localhost:8000/......");
IMyService<string> myService =
    ChannelFactory<IMyService<string>>.CreateChannel(binding, address);
string myObject = myService.GetObject(42);

Again, I'm not sure if this works. The trick is to share your service interfaces (in ServiceInterfaces) and domain model objects (in ModelClasses) between the host and the client. In my example I use a string to return from the service method but it could be any data contract type from the ModelClasses project.

Ronald Wildenberg
i can reference the same assemblies on the client and use the advance tab of the service reference utlity (i am guessing svcutil) to share types, that works, but now i want to make is abstract, guess i am looking for a remotint type solution, but should be possible on wcf ...
You should _not_ use the 'Add Service Reference' dialog in Visual Studio for my approach. That's not going to work. That is why I use the ChannelFactory<TChannel> class. It generates a proxy implementation of your service interface on the fly, without the need for metadata.
Ronald Wildenberg
This most likely won't work (I can't test it right now), since you define a service with operations that return a generic type "T" - but in order to work properly, that type "T" must be a DataContract, so that the WCF stack can serialize and deserialize objects of that type. Remember: all you pass between client and server are **messages** - there's no object reference, or interface reference, or anything reference-based! You **must** be able to serialize your request into some message format, and deserialize it back on the other end - that won't work with generics :-(
marc_s
But suppose that an instance of type T is a proper DataContract (or Serializable or ISerializable), do you think it will work? Given that the class for this instance is shared between Host and Client application. It's not something I'd ever build, but I see no reason why it shouldn't work. I'm going to try and test this out today.
Ronald Wildenberg
@rwwilden: for a given instance of T, maybe - but then why even use generics, if you already have a concrete type? Using generics in a SOA scenario doesn't really help much...
marc_s
@marc_s: I totally agree. I can't think of a case where this would be useful/desired. But it's still an interesting scenario :)
Ronald Wildenberg
I am trying to come up with an interface for a web object repository using which client application can CRUD coarse grained objects (specified by constraints on generic parameters). Then write some custom behaviors to xchange object diffs to do some smart payload object exchanges/caching/instrumentation etc...