Object instances in static classes - c#

I am developing a web application with multiple WCF service references. Currently, each time we need to make a call to a service we do the following(as an example):
Service.ServiceClient ServiceClient = new Service.ServiceClient();
ServiceClient.SomeMethod();
Would it be better to have a static class with static references to each Service and call that class instead, thereby avoiding creating a new instance of the ServiceClient object each time we want to call it?
For example:
public static class Services
{
private static Service.ServiceClient _ServiceClient = new Service.ServiceClient();
public Service.ServiceClient ServiceClient
{
get
{
return _ServiceClient;
}
}
}
And, if doing it this way, would the line
private static Service.ServiceClient _ServiceClient = new Service.ServiceClient();
cause a new object to be created each time we try to call that object, or will it be the same instance of that object every time we make a call to it?

You can have a class which will have all the functions exposed by your data contract. All these methods will be static. Now inside these function you can do as follows
public class ServiceManager{
public static CalculatedData SomeMethod()
{
var client = GetClient();
try
{
return client.SomeMethod();
}
catch(Exception ex)
{
//Handle Error
}
finally
{
if(client.State == System.ServiceModel.CommunicationState.Opened)
client.Close();
}
}
private static SomeClient GetClient()
{
return new ServiceClient();
}
}
Consumer will consume it like
var calculatedData = ServiceManager.SomeMethod();

if you want to do so create
Singleton Service
The singleton service is the ultimate sharable service. When a service is configured as a singleton, all clients independently get connected to the same single well-known instance, regardless of which endpoint of the service they connect to. The singleton service lives forever and is only disposed of once the host shuts down. The singleton is created exactly once, when the host is created.
You configure a singleton service by setting the InstanceContextMode property to InstanceContextMode.Single:
[ServiceBehavior(InstanceContextMode = InstanceContextMode.Single)]
class MySingleton : ...
{...}

It will only be created once, you will have no control however over when it will be created. The usual way to handle this is either create a seperate static method (init for example) where you create the instance or create it when first called. You should check the singleton design pattern for this.

You could use a helper like the following:
private delegate void ServiceAction(Service.ServiceClient client);
private static void PerformServiceAction(ServiceAction serviceAction)
{
using (var client = new Service.ServiceClient())
{
serviceAction(client);
}
}
which can then be invoked the following way:
Helper.PerformServiceAction(client => client.SomeMethod());
It still creates a proxy for every call or sequence of calls but at least your calling code is lighter.
(Keep in mind that using 'using' with a wcf client proxy is not a good idea because dispose might throw an exception so it's better to catch exceptions and to close the proxy gracefully manually).

Related

How to perform a call to an Initialize method of a service with Microsoft DI

I've used other DI framework in the past, now I have to use the microsoft one (.NET Core 3.0) and I need to call a InitializeAsync method when the service is used (It's a singleton so I have only one instance in the whole app). I don't want to perform such operation in the Constructor sincec it has to make a call to a web api , and I also don't want to put a variable inside the method that the service implements and check if it's just initialized.
You can consider the following snippet of code
class Program
{
static void Main(string[] args)
{
using IHost host = CreateHostBuilder(args).Build();
ExemplifyScoping(host.Services, 1);
ExemplifyScoping(host.Services, 88);
host.RunAsync();
}
private static void ExemplifyScoping(IServiceProvider hostServices, int scope)
{
var service = hostServices.GetService<IDummyService>();
var str = service.PerfomSomething(scope);
Console.WriteLine($"RES : {str}");
}
static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.ConfigureServices((_, services) =>
{
services.AddTransient<IDummyService, DummyService>();
}
);
}
and the simplified service class
public class DummyService : IDummyService
{
private IDictionary<int, string> _dictionary;
public Task InitializeAsync()
{
_dictionary = new Dictionary<int, string>();
_dictionary.Add(1,"1");
_dictionary.Add(2,"2");
_dictionary.Add(3,"3");
_dictionary.Add(4,"4");
return Task.CompletedTask;
}
public string PerfomSomething(int id)
{
if (_dictionary.ContainsKey(id))
return _dictionary[id];
return string.Empty;
}
}
public interface IDummyService
{
Task InitializeAsync();
string PerfomSomething(int id);
}
I've seen that the DI framework has a PostConfigure method but I don't know if it's what I need to use.
Any advice?
Thanks
The short answer is that you don't call the InitializeAsync method using the container. Instead you invoke it manually from within your Composition Root.
Letting your DI container invoke an async method (or any method that performs I/O for that matter) is typically a bad idea, because composing object graphs should be fast and reliable. That's why DI Containers usually not expose an ResolveAsync method, because that doesn't make sense in their context.
In your case, you need one-time application wide initialization of a component. This can be done effectively by resolving and invoking the target component after all components have been registered, and the container has been built.
Here's a simple example that demonstrates this:
static async Task Main(string[] args)
{
using IHost host = CreateHostBuilder(args).Build();
await host.Services.GetRequiredService<IDummyService>().InitializeAsync();
...
host.RunAsync();
}
Consider removing the InitializeAsync method from the IDummyService abstraction, and make it available only to the implementation. The InitializeAsync method is an implementation detail and only the Composition Root needs to be aware of it, while the Composition Root already knows about the existence of the implementation (it registered that implementation).
For a more-detailed discussion on the topic of async initialization and DI Containers, see this q/a between Stephen Cleary, Mark Seemann, and myself.
I do encourage you to call it in the constructor maybe as a parallel async. However, I guess you have your reasons to not do so.
Here is how you could do it.
Register the Implementation to itself
services.AddTransient<DummyService, DummyService>();
Register the Interface to a Factory Method
services.AddSingleton<IDummyService>(sp =>
{
var service = sp.GetService<DummyService>();
service.InitializeAsync();
return service;
});

Multi-threading WCF with Singleton Pattern

I have build WCF application and now I would like to run this service as multi-threaded.
I am running three threads in parallel and each thread has WCF service object. at the start of each thread I am executing login function to check user is valid or not & once valid then rest of the methods are gets executed using service object.
My question is, How can I create singleton pattern to create WCF Service object, which will do login are return me service object and same object then shared with multiple threads.
I looked into some articles but they have singleton with lock statement. But lock blocks other thread to use instance.
I need to share service instance with all threads & when all thread release the service object, I have to call logout method.
Any help would be appreciated.
Thanks
public class clsSingleton
{
private static clsSingleton instance = null;
clsSingleton()
{
}
public static clsSingleton Instance
{
get
{
if (instance == null)
{
instance = new clsSingleton();
}
}
}
public string GetName()
{
return "Name";
}
}
//How to call method GetName
string Name= clsSingleton .Instance.GetName();

Using XML Webservices in ASP.Net statically or as a singleton

I have an ASP.Net site that consumes ASP.Net XML webservices. To communicate with each webmethod in the webservice I have a static class with static business methods, one for each webmethod in the webservice. The static business methods create a new instance of the webreference class each time they are called. The new instance of the webreference class is used to only call the webmethod, none of the properties in the instance of the webreference are changed from their defaults.
My question is can I create just a global static instance of the webreference class to use by all of the static business methods instead of creating a new one each time a static business method is called? (Basically are instances of a webreference class thread safe?)
My concern here is that the instance of the webreference class has some properties that are not thread safe and since the code is for a web site, multiple threads calling the same static business methods at the same time would cause issues between the threads.
The reason I'm asking is to try and find additional changes I can make to increase the site's performance. In tracing the site's performance I see a fair amount of time being spent on creating an instance of the webreference class. Additionally based on the garbage collection counters I'm seeing a lot of time being spent there too.
Example Code:
This is what I'm currently doing
public static class WebMethodWrapper
{
public static bool CallMethodA(string p1)
{
using(com.mysite.service1 _provider = new com.mysite.service1())
{
return(_provider.WebMethodA(p1));
}
}
public static bool CallMethodB(string p1)
{
using(com.mysite.service1 _provider = new com.mysite.service1())
{
return(_provider.WebMethodB(p1));
}
}
}
This is what I'd like to do
public static class WebMethodWrapper
{
static com.mysite.service1 _Provider = null;
static WebMethodWrapper()
{
_Provider = new com.mysite.service1();
}
public static bool CallMethodA(string p1)
{
return(_Provider.WebMethodA(p1));
}
public static bool CallMethodB(string p1)
{
return(_Provider.WebMethodB(p1));
}
}
My question is can I create just a global static instance of the webreference class to use by all of the static business methods instead of creating a new one each time a static business method is called? (Basically are instances of a webreference class thread safe?)
My concern here is that the instance of the webreference class has some properties that are not thread safe and since the code is for a web site, multiple threads calling the same static business methods at the same time would cause issues between the threads.
A jolly good question to which it seems you are well on the way to answering. I agree you should probably stick with your current approach where each static method creates its own local copy of the service client. This encourages thread-safety not only from the point of view of the client, but also guarantees that remote calls to the service are done so using unique proxies - where results are not potentially multiplexed with other requests.
If you went down the other route of using a shared instance, then you have to take into consideration those scenarios where the service faults in one thread.
Maybe there was a timeout?
Maybe some remote business logic failed?
Maybe the network failed because your room-mate is downloading the latest episode of Game of Thrones exceeding your download quota?
You would then need to invalidate that client and recreate a new one. All of this would need to be safely thread-locked. It sort of becomes quite complex to manage this orchestration.
Let's consider your alternative code:
public static bool CallMethodA(string p1)
{
return(_Provider.WebMethodA(p1));
}
Let's say this was successfully called the first time. Now imagine you need to call this 5 mins 5 seconds later but sadly by this time the server has severed the connection because it has a timeout of 5 mins. Your second call faults. The above code would need to be adjusted to allow for those scenarios. In our simple example below we recreate the client during a failure and try once more.
Perhaps:
public static class WebMethodWrapper
{
static com.mysite.service1 _Provider = null;
static object _locker = new object();
static WebMethodWrapper()
{
_Provider = new com.mysite.service1();
}
static com.mysite.service1 Client
{
get
{
lock (_locker)
{
return _Provider;
}
}
}
public static bool CallMethodA(string p1)
{
try
{
return (Client.WebMethodA(p1));
}
catch (Exception ex) // normally just catch the exceptions of interest
{
// Excercise for reader - use a single method instead of repeating the below
// recreate
var c = RecreateProxy();
// try once more.
return (c.WebMethodA(p1));
}
}
public static bool CallMethodB(string p1)
{
try
{
return (Client.WebMethodB(p1));
}
catch (Exception ex) // normally just catch the exceptions of interest
{
// Excercise for reader - use a single method instead of repeating the below
// recreate
var c = RecreateProxy();
// try once more.
return (c.WebMethodB(p1));
}
}
static com.mysite.service1 RecreateProxy()
{
lock (_locker)
{
_Provider = new com.mysite.service1();
return _Provider;
}
}
}
All of this could be wrapped-up in some generic service client cache that could maintain a collection of ready-to-go clients in a connection pool? Maybe a background thread periodically pings each client to keep them alive? An exercise for the reader perhaps.
Then again, sharing the same proxy instance between threads may not be a good idea from the service point of view, unless your service is marked as per-call which may or may not impact your design or performance.
Conclusion
Your current code is arguably safer and less complex.
Good luck!

Variation on Service Locator

IModificationRequst<Employee> req = new ModificationRequst();
Locator.Instance.GetService<IModificationRequstHandler<Employee>>().Handle(req);
I have a service locator that locates services that returns instances of objects implementing IModificationRequstHandler.
I am trying to modify it to rather than returning a IModificationRequstHandler implementer, it is just internally finds the service and invokes it's handler method, so the above 2 lines would look like this instead:
IModificationRequst<Employee> req = new ModificationRequst();
Locator.Instance.HandleRequest<IModificationRequst<Employee>>(req);
But having hard time with the generics, is there an already established pattern for resovling the requests to their proper request handlers and invoking their handling, rather than getting a handler and then invoking their Handle method from the client?
That violates Single Responsibility Principle. You should not make the service locator implement logic for different services.
If you do want to use static classes you should add another one:
public static class RequestHandler
{
public static void Handle<T>(T request)
{
Locator.Instance.GetService<IModificationRequstHandler<T>>().Handle(req);
}
}
And then:
IModificationRequst<Employee> req = new ModificationRequst();
RequestHandler.Handle(req);
(Sidenote: You might look up Dependency Injection & IoC containers since it makes the code more maintainable)
Your HandleRequest method in the locator class should be defined as follows (assuming Handle has a return type of void):
public void HandleRequest<T>(IModificationRequest<T> req)
{
IModificationRequstHandler<T> handler = GetService<IModificationRequest<T>>();
handler.Handle(req);
}
and your IModificationRequstHandler interface should be defined as follows:
public interface IModificationRequstHandler<T>
{
void Handle(IModificationRequst<T> req);
}
and your call will then become:
Locator.Instance.HandleRequest(req);
The generic type parameter Employee here is inferred from the parameter value req and thus does not need to be specified.

Global Variable between two WCF Methods

I have two Methods in a WCF Service say
Method1()
{
_currentValue = 10;
}
Method2()
{
return _currentValue;
}
I have a situation in which, i need to set a value in Method1() and read it in Method2().
I tried using static variable like public static int _currentValue, i could able to read the value set in Method1() in Method2().
But the issue is, i want this variable to react like separate instance variable for each request made. i.e., right now below is the problem
Browser 1 :
- Method1() is called
=> sets _currentValue = 10;
- Method2() is called
=> returns _currentValue = 10;
Browser 2:
- Method2() is called
=> returns _currentValue = 10;
Actually the value set is Browser 1 is static, so in Browser 2
the same value is retrieved.
What i am trying to implement is the variable should act like a new instance for each request made (when calling from each browser). What should i use in this case? a session?
You're going to need some mechanism for correlation because you have two completely different sessions calling into different methods. So I would recommend using a private key that both callers know.
It is a bit impossible for me to know what that key can be because I can't really gather anything from your question, so only you know that, but the simple fact is you're going to need correlation. Now, once you determine what they can use you can do something like this.
public class SessionState
{
private Dictionary<string, int> Cache { get; set; }
public SessionState()
{
this.Cache = new Dictionary<string, int>();
}
public void SetCachedValue(string key, int val)
{
if (!this.Cache.ContainsKey(key))
{
this.Cache.Add(key, val);
}
else
{
this.Cache[key] = val;
}
}
public int GetCachedValue(string key)
{
if (!this.Cache.ContainsKey(key))
{
return -1;
}
return this.Cache[key];
}
}
public class Service1
{
private static sessionState = new SessionState();
public void Method1(string privateKey)
{
sessionState.SetCachedValue(privateKey, {some integer value});
}
public int Method2(string privateKey)
{
return sessionState.GetCachedValue(privateKey);
}
}
It sounds like you may need to use the per session instance context mode for the WCF service. This will allow you to maintain state on a per session basis, so member variables in the service instance will persist between method calls from the same proxy instance. Because each user has their own session, the state of the service instance will vary by user.
Check out this article for more information: http://msdn.microsoft.com/en-us/magazine/cc163590.aspx#S2
You have made your variable static, and this is what's causing the problem. static means that every instance of your class shares the variable, but all you really need is a variable declared outside of your methods, like this:
private int _currentValue;
Method1()
{
_currentValue = 10;
}
Method2()
{
return _currentValue;
}
This variable will be reated separately for each instance of your class - preserving this value between requests for a given user is a separate problem. (A session is one possible solution.)
WCF has provided three ways by which you can control WCF service instances:
Per call
Persession
Single instance
You will find the best solution by reading this
Three ways to do WCF instance management
Seems like an old thread but in case somebody is still interested, this can be achieved by just asking WCF to run a single instance of your service. Add the following line (decorator) to the definition of your class
[ServiceBehavior(InstanceContextMode = InstanceContextMode.Single)]
If you want the behavior only for the same session but not across clients then you can mark it as per session by the following service behavior
[ServiceBehavior(InstanceContextMode = InstanceContextMode.PerSession)]
The other option is per call which is the default option.
[ServiceBehavior(InstanceContextMode = InstanceContextMode.PerCall)]

Categories

Resources