Hi, I observed that there is no channel factory caching in comparison to full .Net FW version.
Any plans to get that added?
@DotNetPart you are correct about this. The reason of this change is because 1) .NET Core does not support configuration like full .NET does so ctors that takes endpointConfigurationName are not supported, which is also used for caching and 2) System.ServiceModel.CacheSetting API is not available on .NET Core.
So even if necessary APIs were added to .NET Core, caching has to be done by code. User code can cache channel factory instance explicitly today and it will be less ambiguous, which is our recommendation for .NET Core.
@zhenlan Thanks. That's what I exactly what I ended up doing.
Not sure though how constructor parameter affects caching and why we can't cache based on Binding/EndpointAddress.
In regards to CacheSetting - this is just an enum as I remember. Is it a problem to add this enum due to process or there is some other reason?
@DotNetPart you are right again about Binding/EndpointAdress. Yes, we can cache based on them and it's not a problem to add CacheSetting enum. However, as you can imagine the logic can get complicated very quickly when you have to decide when to use a cached instance and when to create a new instance etc., whilst it's a fairly simply task to cache in user code and a user has full control of what to use (no magics). This is the reason we are leaning towards not to add this caching complexity. Please let us know if you have a compelling reason you think otherwise.
@zhenlan no worries. I was just curious on the reasoning and how it aligns with current strategy.
I'm good with implementing this caching myself (which I did as you know).
The reason on why it would be good to implement caching is that when I have used ClientBase
I completely agree that it's not always possible, but aren't we building frameworks/libraries for people to save their time?
I'm not arguing, it's just an open question. Maybe I didn't get .NET Core philosophy yet.
@DotNetPart, a bit more context. ClientBase has multiple constructors, and different constructors had different caching behavior. The constructor which takes an endpoint configuration name (from an app.config file) uses caching by default as you are only specifying the name in the config file which means one instance will have an identical configuration to the next. For constructors which are functional in .Net Core taking a Binding and EndpointAddress, it would be very complicated and error prone to verify that the Binding passed to one instance of ClientBase is identical to the Binding passed to another, so that constructor had caching disabled by default. On the full framework, you can override the default caching behavior with the CacheSetting property, but even if you enable it there are scenarios where you can inadvertently disable it. There are a few things you can do with a ClientBase object which will trigger attempting to disable sharing of the ChannelFactory. These conditions are quite complex, convoluted and highly dependent on existing state and have often lead to confusion on the full framework. Developers have been in the situation where they enable caching, and then then later modify a property on the ClientBase which disabled caching and suddenly their memory usage increased significantly. The primary use case for caching was when using an endpoint configuration name which isn't applicable to .Net Core. So rather than continuing to have developer confusion about when a factory is and isn't cached, as the default was not to cache with the usable constructors we decided not to add this. It's trivial to have a static property to hold a single instance of ClientBase in your own code and is completely unambiguous as to when you are caching.
@mconnew thanks for the detailed answer. That makes perfect sense now.
Most helpful comment
@DotNetPart you are right again about Binding/EndpointAdress. Yes, we can cache based on them and it's not a problem to add CacheSetting enum. However, as you can imagine the logic can get complicated very quickly when you have to decide when to use a cached instance and when to create a new instance etc., whilst it's a fairly simply task to cache in user code and a user has full control of what to use (no magics). This is the reason we are leaning towards not to add this caching complexity. Please let us know if you have a compelling reason you think otherwise.