问题
We are using WCF and Visual Studio 2008 to build a large, distributed application. We don't have much experience with WCF so we are investing some time in prototyping the WCF communications between clients and server. We have observed that any class referenced by the WCF services in our server subsystem as a parameter or return type is "copied" into the client proxy by Visual Studio through generated code. What I found surprising was that, when doing this, Visual Studio alters the namespace of the classes. For example, imagine that I have the following code:
namespace MyLibrary
{
class MyClass
{
//...
}
}
And imagine that I compile that into MyLibrary.dll
, to which my WCF services have a reference. Some of my WCF services use MyLibrary.MyClass
as a return type. When I look at the generated client proxy code, I find MyClass
to be automagically available (which is cool), but it is not in the MyLibrary
namespace anymore but in one generated by Visual Studio.
We are planning to have a complex domain object model with hundreds of classes distributed across multiple assemblies, and I am concerned about how well this will "port" across the code generation that Visual Studio does. Also, I am concerned that all the nice hierarchy of namespaces that we have designed will be probably lost. Our initial vision was to create class libraries for this domain object model and delpoy it on both server and client. But since WCF magic seems to generate code for the necessary classes, I imagine that there would be a conflict if we deploy our own libraries on the client.
I have two specific questions then:
- Is there a way to make Visual Studio use the original namespace scheme rather than its own when generating client proxy code? If not, will this affect the usability of our "copied" libraries on the client?
- Can I deploy the original libraries on the client nevertheless? I imagine not, but what kind of clash would that cause?
Thank you.
回答1:
When you add a service reference you can click the "Advanced" button, in there you can check the box that reads "Reuse types in referenced assemblies". You will also need to make sure you have the assembly that contains the original types referenced in the client project.
You can of course deploy the original libraries on the client.
The reason WCF does this - the concept is that the services could be consumed by a client that doesn't have your original binaries, or even doesn't support .net (e.g. Java) - therefore the service boundary publishes everything a client would need in order to call it, and deal with its response.
回答2:
From my recent experience implemented WCF in a very large and old project, I would avoid the Visual Studio templateing features like the plague (for large projects), it's just going to give you a headache and phantom problems down the road.
http://www.codeproject.com/Articles/114139/WCF-The-Right-Way-A-Quick-Reference-Guide
Check out that article. It answers your current questions and likely will prevent a lot of future headaches.
In addition to the above, if you have a good implementation and isolation of your transport layer you can absolutely reuse components, it's a big reason for NOT using the VS Templates.
回答3:
Your initial vision is totally possible. A way of avoiding the visual studio generated clients and is to create a generic client which shares the library service interface with the server, as well as the implementation of the binding (the latter is not neccessary though, it can be done with identical server/client binding configurations in app.config, but it's convenient if final setups are similar).
Some client-side c# example code to get the idea:
// simplified extract from a generic service client lib,
// needs error mgmt channel disposal etc but the concept is there
// BindingFactory is our common implementation with server,
// bindingType is an enumeration, this could be built from
// configuration though or however you want
var binding = BindingFactory.CreateBinding(bindingType);
var endpointAddress = new EndpointAddress(serviceAddress,
EndpointIdentity.CreateSpnIdentity(string.Empty))
var channelFactory = new ChannelFactory<IMyLibrary>(
binding, endpointAddress);
var channel = channelFactory.CreateChannel();
// IMyLibrary is the interface implemented
// by the service found on serviceAdress
var result = ((IMyLibrary)channel).MyServiceFunction();
来源:https://stackoverflow.com/questions/14937718/copied-classes-in-wcf-proxy-code