1

I read that we're not supposed to use using around WCF Client. So I found this awesome answer how to write elegant code around it.

It's not perfect, cause it's not async and it doesn't return any value, so I created my version (based on other answers):

    public static async Task<TReturn> UseServiceAsync<TChannel, TReturn>(Func<TChannel, Task<TReturn>> code)
    {
        ChannelFactory<TChannel> _channelFactory = new ChannelFactory<TChannel>("NetTcpBinding_IMyService");
        TChannel channel = _channelFactory.CreateChannel();
        bool success = false;
        try
        {
            TReturn result = await code(channel);
            ((IClientChannel)channel).Close();
            success = true;
            return result;
        }
        finally
        {
            if (!success)
            {
                ((IClientChannel)channel).Abort();
            }
        }
    }

It works great, but.. I don't want to specify my endpoint in the ChannelFactory. I provided contract interface already! It's totally enough to go to the config file and look for that endpoint. Why do I have to specify it explicitly?

BTW. In the mentioned answer, there is a link to the article.. and they do something like this:

public static ChannelFactory<T> _channelFactory = new ChannelFactory<T>("");

How is that supposed to work?? I don't know..

My question to you guys is: How to create ChannelFactory without passing endpoint name explicitly?

Marshall
  • 255
  • 1
  • 4
  • 11

1 Answers1

1

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 ) ) );
    }
}
Sievajet
  • 3,443
  • 2
  • 18
  • 22
  • Thanks for help, but I'm not sure about this way. It validates *DRY principle*, because I will have `"http://localhost/service"` in both `app.config` and `SomeChannelFactory`. – Marshall Mar 22 '18 at 23:08
  • You can achieve that with dependency injection. Use any of the other `InitializeEndpoint` overloads if required. – Sievajet Mar 22 '18 at 23:09
  • I'm not sure if I understood. My point is: there are two places in the code, where *"http://localhost/service"* appears. So if you want to change the address you will have to change it in two places. It creates potential issues, because what if someone would change only one address in the config? Why would he know that he should change the class too? Do you understand my point? – Marshall Mar 22 '18 at 23:16
  • you should inject the address in the constructor of the class. this way the only place where the address is located, is in the config. – Sievajet Mar 22 '18 at 23:20
  • How can I do it though? Inject something into App.config? – Marshall Mar 23 '18 at 00:17
  • Can you explain me this: "you should inject the address in the constructor of the class. this way the only place where the address is located, is in the config". It sounds really interesting.. I would really appreciate it – Marshall Mar 23 '18 at 03:13
  • Just read the address from the config file and pass it as parameter into the constructor when you instantiate the custom factory. This way you only to define the address only in the config file. – Sievajet Mar 23 '18 at 07:07