Reputation: 1425
Lets say I have some interfaces:
public interface IFoo {
IBar DoesStuff();
}
public interface IBar {
string Thingo { get; }
}
I'm consuming this code throughout my code base. The IFoo process needs to be moved onto a different system (a difference of x64 vs x32), this is our reason for using WFC. My WCF service implements this interface. When I create the "service reference" the proxy stubs are created but the interface is altered.
public interface IFoo {
object DoesStuff();
}
I tried defining IBar/Bar as both a DataService and DataContract with no difference. Is there a way to generate the proxy code using my interface?
I'm thinking if mock objects can produce a object of my interface for testing, then shouldn't I be able to get the service to honor it as well? Or did do something silly and wrong?
Upvotes: 4
Views: 6772
Reputation: 31
Another way to skin the cat. Dominic has done it using KnownType attributes. Check out his blog below.
http://blogs.msdn.com/b/domgreen/archive/2009/04/13/wcf-using-interfaces-in-method-signatures.aspx
Upvotes: 0
Reputation: 31
I don't know if you still need a solution. Below is what I'd do. The trick here is not to use the standard "add service references" like many blogs has suggested but rather writer your own client proxy using Channel Factory. In this case, you can choose to reuse your interfaces but redefine the concrete classes as required. Happy to elaborate further if you need.
// Service Contract
[ServiceContract(name="a", namespace="b")]
public interface IFoo {
Bar DoesStuff();
}
// Interface to share
public interface IBar {
string Thingo { get; }
}
// Server Implementation
public class Bar : IBar
{
string Thingo { get; set; }
}
// Client Proxy reference IBar interface only but redefine concrete class Bar.
public class Bar : IBar
{
public string Thingo
{
get { return _thingo; }
set { _thingo = value; }
}
string _thingo;
}
/// Sample channel factory implementation
using System;
using System.Configuration;
using System.ServiceModel;
using System.ServiceModel.Channels;
public abstract partial class ServiceProxyBase<TServiceContract> : IServiceProxy
where TServiceContract : class
{
protected ServiceProxyBase()
: this(null, null)
{
}
protected ServiceProxyBase(string url, Binding binding)
{
var contractName = typeof(TServiceContract).Name;
var urlConfiguration = string.Format("{0}_Url", contractName);
var serviceUrl = url ?? ConfigurationManager.AppSettings.ValueOrDefault (urlConfiguration, string.Empty, true);
if (serviceUrl.IsNullOrEmptỵ̣())
{
throw new Exception(string.Format("Unable to read configuration '{0}'", urlConfiguration));
}
var serviceBinding = binding ?? new BasicHttpBinding();
Factory = new ChannelFactory<TServiceContract>(serviceBinding);
var serviceUri = new Uri(serviceUrl);
var endPoint = new EndpointAddress(serviceUri);
Channel = Factory.CreateChannel(endPoint);
}
public virtual void Abort()
{
isAborted = true;
}
public virtual void Close()
{
if (Channel != null)
{
((IClientChannel)Channel).Close();
}
if (Factory != null)
{
Factory.Close();
}
}
private ChannelFactory<TServiceContract> Factory { get; set; }
protected TServiceContract Channel { get; set; }
private bool isAborted = false;
}
public class FooServiceProxy : ServiceProxyBase<IFooServiceProxy>, IFooServiceProxy
{
public Task<Bar> DoesStuffAsync()
{
return Channel.DoesStuffAsync();
}
}
[ServiceContract(name="a", namespace="b")] // The trick when redefine service contract
public interface IFooServiceProxy
{
[OperationContract]
Task<Bar> DoesStuffAsync();
}
Upvotes: 2
Reputation: 72840
Yes. You need to reference the project containing the interface before you add the service reference. Then the interface will be re-used. The same will be true for any custom classes used - if the project containing their definitions is referenced by the client project before the service reference is added, then WCF can re-use those definitions.
You will also need to go to the Advanced tab in the Add Service Reference dialog and tick "Reuse types in referenced assemblies" to get this to work.
Upvotes: 1
Reputation: 161773
Try to think of web services as being cross-platform. What would a Java client do with your interface if you returned it?
Upvotes: 1
Reputation: 19117
IBar needs to be concrete and a DataContract. WCF isn't about distributed objects, but rather a way to transfer data and have services work on that data. You can't return an object in WCF that has behavior.
Upvotes: 6