creating WCF ChannelFactoryT
Yes, if you want to create something like this - a static class to hold all those ChannelFactory<T>
instances - you definitely have to make sure this class is 100% thread-safe and cannot stumble when accessed concurrently. I haven't used .NET 4's features much yet, so I cannot comment on those specifically - but I would definitely recommend to make this as safe as possible.
As for your second (minor) question: the ChannelFactory itself is a static class - so you cannot really call a .Close()
method on it. If you meant to ask whether or not to call the .Close()
method on the actual IChannel
, then again: yes, try your best to be a good citizen and close those channels if you ever can. If you miss one, .NET will take care of it - but don't just toss your unused channels on the floor and go on - clean up after yourself! :-)
Creating WCF ChannelFactory without an endpoint?
ChannelFactory<TChannel>
derives from abstract class ChannelFactory
. Create a custom derived class and use the InitializeEndpoint
call to initialize the endpoint.
For example:
public class SomeChannelFactory : ChannelFactory
{
public SomeChannelFactory()
{
InitializeEndpoint( new BasicHttpBinding() , new EndpointAddress( "http://localhost/service" ) );
}
protected override ServiceEndpoint CreateDescription()
{
return new ServiceEndpoint( new ContractDescription( nameof( SomeChannelFactory ) ) );
}
}
How does ChannelFactory (WCF/C#) use an Interface as a type?
Internally, ChannelFactory<TChannel>
creates an object of type ServiceChannelProxy
, which derives from System.Runtime.Remoting.Proxies.RealProxy, allowing it to create a transparent proxy over the TChannel
interface.
WCF channel Factory caching
This is a complex topic with a lot of details to go over, but here it goes.
First, as a general rule you should be caching a ChannelFactory
and not an individual Channel
. A ChannelFactory
is expensive to construct as well as thread-safe so it is a great candidate for caching. A Channel
is cheap to construct and it is generally recommended to only create channels on an as-needed basis and to close them as early as possible. Additionally, when you cache a Channel
then you have to worry about it timing out which will cause it to fault which invalidates the entire benefit of caching it in the first place.
The article you linked to by Michele Leroux Bustamante is one of the best resources out there. As she states, there are differences to consider between Windows clients and server-side clients. Mostly only Windows clients benefit from caching as typically the credentials differ from thread to thread on server-side clients. For your typical Windows clients, there are two main options: Caching the references yourself or leveraging the MRU cache.
Leveraging the MRU cache: Essentially this means that you are letting Microsoft take the wheel. The ClientBase
class will use an MRU cache for the internal ChannelFactory
instance. The caching behavior is controlled via a CacheSetting
property and by default caching will be disabled if any of the "security-sensitive" properties are accessed. ClientBase
properties which will invalidate and remove a ChannelFactory
from the MRU cache when accessed include the Endpoint
, ClientCredentials
or the ChannelFactory
itself. There is a way to override this behavior by setting the CacheSettings
property to CacheSettings.AlwaysOn
. Additionally, if the Binding
is run-time defined then the ChannelFactory
is no longer a candidate for the MRU cache. See more details here.
Caching the references yourself: This means that you are going to keep a collection of ChannelFactory
references yourself. The snippet you provide in your question uses this approach. The best approach I have ever seen and admittedly use a modified version of at work is by Darin Dimitrov via this related SO question. For those of us who like to have more fine-grained control over the caching mechanism then this is the approach to use. This is typically used when credentials must be set at run-time like is often required by internet services.
Quite similarly, client proxies can be cached to improve performance - Wenlong Dong has an article about this topic.
(Update) Server-side clients as noted before are quite limited in their options when it comes to ChannelFactory
caching. For this brief discussion, we will assume that our deployment scenario looks like this:
Client -> Service A -> Service B
The most likely method to use in order to leverage ChannelFactory
caching in this scenario is to cache the references yourself for the session between the Client and Service A. This way Service A does not have to construct a different ChannelFactory
instance every time Service A needs to call into Service B. However, if the properties of the ChannelFactory
need change for each call, then this is no longer going to be appropriate.
Of course this also holds if Service A is a Singleton and each call to the downstream service (Service B) does not require new credentials, but Singleton services have their own set of performance problems.
Using ChannelFactoryT To Create Channels with Different Credentials
As documented on MSDN this is not directly possible (Credentials
become readonly upon Open
of the ChannelFactory
)... if you really want to do this you will need to trick the ChannelFactory
like this:
// step one - find and remove default endpoint behavior
var defaultCredentials = factory.Endpoint.Behaviors.Find<ClientCredentials>();
factory.Endpoint.Behaviors.Remove(defaultCredentials);
// step two - instantiate your credentials
ClientCredentials loginCredentials = new ClientCredentials();
loginCredentials.UserName.UserName = "Username";
loginCredentials.UserName.Password = "Password123";
// step three - set that as new endpoint behavior on factory
factory.Endpoint.Behaviors.Add(loginCredentials); //add required ones
Another option seems to be to Close()
the ChannelFactory
before trying to change the Credentials
.
Otherwise just stick with caching different ChannelFactories for different Credentials...
WCF Cannot create channel factory with given endpoint name
You need to add an <endpoint>
under a <client>
element to be able to call it from ChannelFactory
:
Add the following code under <system.serviceModel>
:
<client>
<endpoint address="net.tcp://localhost:8090/TexasHoldem" binding="netTcpBinding" bindingConfiguration="" contract="Service.ITexasHoldemService" name="TexasHoldem">
</endpoint>
</client>
ChannelFactory: creating and disposing
Thanks Daniel, didn't see that post. So I guess that the following may be a good approach:
public class ProjectStudioServiceFactory : IDisposable
{
private static IProjectStudioService _projectStudioService;
private static ChannelFactory<IProjectStudioService> _channelFactory;
public IProjectStudioService Instance
{
get
{
if (_projectStudioService == null)
{
_channelFactory = new ChannelFactory<IProjectStudioService>("ProjectStudioServiceEndPoint");
_projectStudioService = _channelFactory.CreateChannel();
((IClientChannel)_projectStudioService).Open();
}
return _projectStudioService;
}
}
public void Dispose()
{
//((IClientChannel)_projectStudioService).Close();
//_channelFactory.Close();
}
}
Related Topics
The Maximum Number of Characters a Textbox Can Display
What Does It Mean for a Property to Be [Required] and Nullable
How to Post a List of Items in MVC
Why Was "Switchto" Removed from Async Ctp/Release
Using Layers and Bitmask with Raycast in Unity
Is There a Generic Constraint I Could Use for the + Operator
Windows.Ui.Notifications Is Missing
How to Handle JSON That Returns Both a String and a String Array
Using the "Params" Keyword for Generic Parameters in C#
How to Backup and Restore the System Clipboard in C#
How to Treat the Circle as a Control After Drawing It? - Moving and Selecting Shapes
Mysqlcommand Command.Parameters.Add Is Obsolete
How to Select Text from the Richtextbox and Then Color It
Internet Explorer Protective Mode Setting and Zoom Levels
What Is the Worst Gotcha in C# or .Net
Are There Any Suggestions for Developing a C# Coding Standards/Best Practices Document
Retrieve Credentials from Windows Credentials Store Using C#