Dispose object instance(s) on application exit/crash with WPF / Prism - c#

I'm using the prism framework for my WPF application with DryIoc, but maybe I don't quite understand some of it's uses. (Self-taught) or best practises.
I have a class library (MyLibrary) that follows a disposable pattern as it needs to do some clean-up.
I have a module that uses MyLibrary in its view model.
If the application is closed or even on an application crash, I would like to call dispose on this library, just in case it isn't already disposed of correctly at this time (otherwise it will leave third party apps open in the background)
There is currently only 1 instance, but could be more than 1 in the future.
So far, this is what I have come up with:
When my view model first requires MyLibrary it will register an instance, like so:
this.ce.RegisterInstance<MyLibrary>(this.myLibrary, "MyLibraryName"); where ce is Prism.Ioc.IContainerExtension
and then in the protected override void OnExit(ExitEventArgs e) method in my App.xaml.cs I will do: this.Container.Resolve<MyLibrary>("MyLibraryName")?.Dispose();
This successfully disposes my library object (and closes the 3rd party windows as i expect it to), however, it just seems a bit off to me (Code smell?)
Is there a better way to do it? I don't feel like the App.xaml.cs should have to know about the instance name that my module's view model came up with for example. Is there a way to just call Dispose on all MyLibrary types in the container without the name string?
I was hoping I could iterate over all MyLibrarys in the container and call Dispose?
If there isn't a better way then I'm ok with it I suppose.
But just as important: How can I attempt to call Dispose in a similar fashion on any unhandled exceptions that would otherwise crash the app? Can I access the container somehow and dispose of any MyLibrarys?
I wouldn't intend to try and save the app from crashing, just make sure that MyLibrary calls its Dispose method.
Comment response (Too many characters):
Click UI button> Delegate command> code written in method in VM.
The Library has an overhead to start up(sign in).
There are multiple input steps on the UI that requires use of the library.
Wrapping it in a using at each stage (button click) is not impossible, but it is inefficient because of the libraries startup overhead.
I want to:
- Instantiate library
- User inputs data, library does work, returns results, requires more input etc
- Several more of these data input stages / library work / results
- Dispose
Problem:
- User exits application before library object is disposed
- How/Where to dispose?
Attempted solution:
- Use the container so that i can dispose in App.xaml.cs `OnExit`
- This solution works, but feels incorrect?
Question: What can I do better/different in this situation?
Additional question: How do I handle disposing this upon a fatal crash in a prism app?
It's important that it gets disposed of so that instances of 3rd party apps that the library utilises are not left running in the background.

Ok, I changed it to register an instance in app.xaml.cs now and I can avoid the .Resolve call. Would you do it like this? If not then how? When it was registered as a singleton I had no idea how to get it in OnExit without the .Resolve
Cut-down/simplified example of my app.xaml.cs now:
namespace MyNamespace
{
public partial class App
{
public App()
{
// Crash handling
this.Dispatcher.UnhandledException += this.OnDispatcherUnhandledException;
}
// My library provider that contains a dictionary of library instances.
public IMyProvider MyProvider { get; set; } = new MyProvider();
// Dispose provider on crash
public void OnDispatcherUnhandledException(object sender, System.Windows.Threading.DispatcherUnhandledExceptionEventArgs e)
{
this.MyProvider.Dispose();
MessageBox.Show("Unhandled exception occurred: \n" + e.Exception.Message, "Error", MessageBoxButton.OK, MessageBoxImage.Error);
}
protected override Window CreateShell()
{
return this.Container.Resolve<MainWindow>();
}
// Register as an instance?
protected override void RegisterTypes(IContainerRegistry containerRegistry)
{
containerRegistry.RegisterInstance<IMyProvider>(this.MyProvider);
}
protected override void ConfigureModuleCatalog(IModuleCatalog moduleCatalog)
{
// Add modules here...
}
protected override void OnExit(ExitEventArgs e)
{
base.OnExit(e);
// Dispose my provider (and all contained instances in its dictionary)
this.MyProvider.Dispose();
}
}
}

Comment character limit preventing me from writing too much again.
#Haukinger: tl;dr: You got me on the right track.
I didn't quite follow your example exactly to the letter (not using Lazy, library doesnt have an interface), but you got me on the right track.
Overall, I'm struggling to wrap my head around: DI, IoC, Interfaces and how they all relate.
Your line about abusing the container got me to look a little closer at it.
First, I removed all instances of containerExtension.resolve from view models and instead injected into the constructor as it should have always been.
I created a provider similar to what you suggested and a provider interface for my library.
The provider implementation keeps a dictionary of named library instances in case I require multiple.
I still call this.Container.Resolve<IMyProvider>().Dispose(); in the application's OnExit but it feels better because I don't have to name an instance any more.
Just having a provider interface still doesn't stop anyone from new-ing up library instances themselves though?
Library interface is registered like so:
containerRegistry.RegisterSingleton<IMyProvider, MyProvider>();
Other than my library:
I'm currently registering a few application wide instances for a few things like application theme in the container like so: containerRegistry.RegisterInstance<MyThing>(this.MyThing);
Still not using interfaces here. Still trying to understand them, but an application wide instance for theme in the container is working just fine.
From examples I've seen where IAnimal interface can have a Dog and a Cat implementation, my objects don't have multiple implementation requirements. (Besides unit testing which I'm yet to attempt to learn and I assume I will benefit from interfaces in this situation) I just need access to some things from different modules/assemblies and was using the container to do so.
One of my biggest problems was that I have parameters to construct some instances like my library and the parameters are not known until run time, so I couldn't register an instance in app.xaml.cs when the app starts.
If I have to construct something with parameters that are only known at runtime (credentials for example) Do I need to follow a sort of factory pattern with an interface to be able to register them or am I missing something?
I guess I could register an instance with the container extension at the time they get created (in assembly A's view model A)? but then I would need to use .Resolve later if I want them in a different module (Assembly B's view model X)?
Which doesn't feel right, and creating a factory and a factory interface for a simple credentials object feels overkill?
I think I'm just not fully understanding interfaces, as examples I've seen often dont have parameters for the implementation or they focus on discussing the benefits of different implementations when I will only have 1 implementation.
Or examples have nothing to do with IoC or DI.
As far as handling disposing on application crash event I did the following:
public App()
{
this.Dispatcher.UnhandledException += this.OnDispatcherUnhandledException;
}
public void OnDispatcherUnhandledException(object sender, System.Windows.Threading.DispatcherUnhandledExceptionEventArgs e)
{
// Dispose provider
this.Container.Resolve<IMyProvider>().Dispose();
// Unhandled exception messagebox:
MessageBox.Show("Unhandled exception occurred: \n" + e.Exception.Message, "Error", MessageBoxButton.OK, MessageBoxImage.Error);
}
I'm still tearing my hair out over interfaces / factory pattern / DI / Ioc / General design, but you got me on the right track.
I'm injecting stuff into constructors better, I can manage my library instances with the provider and dispose on exit and on crash is working.
Thanks.

I suggest you do not try to abuse the container here.
Instead, create a manager for your library yourself and clean that one up at shutdown:
public interface ILibraryProvider : IDisposable
{
ILibrary GetLibrary();
}
internal class LibraryProvider : ILibraryProvider
{
public LibraryProvider( Lazy<ILibrary> library )
{
_library = library;
}
#region ILibraryProvider
public ILibrary GetLibrary() => _library.Value;
public void Dispose()
{
if (_library.IsValueCreated)
_library.Value.Dispose();
}
#endregion
#region private
private readonly Lazy<ILibrary> _library;
#endregion
}
In Application.OnExit, dispose the LibraryManager.
If you need multiple, distinct libraries, add a string parameter to Get, inject a Func instead of a Lazy and store the instances in a Dictionary.

Related

Implementing Delegate In .NET SAP Connector

Quite a specific question and probably basic on some levels. I have a gap in my knowledge of delegates and event handling in general so I'm not surprised that I am a bit stuck. But using Autofac is complicating matters in my understanding even more. I'll try and explain below.
I am connecting to SAP using the .NET V3 SAP connectors and implementing what's known as an RFC Server. As part of that the good people at SAP have exposed an RfcServerErrorEventHandler:
public delegate void RfcServerErrorEventHandler(object server, RfcServerErrorEventArgs errorEventData);
I start my server in a class library in which I have what we'll call a server manager. It is to start the server, stop it and everything inbetween. What I am stuck with is how on earth I can go about using the above delegate in my server manager class, which is injected using AutoFac to my main program with the implementation as below:
public IServerManagerService _ServerManager;
public ApplicationLogic(IServerManagerService serverManager)
{
_ServerManager = serverManager;
}
_ServerManager.StartServer(ServerName);
The above goes to the server manager class and runs the StartServer method obviously. I have attempted to try and register the event (this is where I am hazy) as below in the server manager class:
public void ErrorHandler(object sender, RfcServerErrorEventHandler e)
{
throw new Exception("The method or operation is not implemented.");
}
But can I for the life of me figure out how to either get the delegate hooked up to this or figure out how to do it via autofac. I have had some attempts but I just cant find any examples of this anywhere online. It seems that SAP .NET Connectors are quite a niche thing. The connector documentation provides only very basic code samples also.
I think my problem as mentioned is just a lack of basic event handling techniques possibly or esp when using with DI. I have done a fair amount of reading before posting but just not getting it.
Thanks in advance
This should be explained in any good C# book: see the topics "delegate" and "event". Basically, you can register an event handler at a certain event simply by using the += operator. ("=" should also work, if you are the only one using the RfcServer, but with "+=" you can have more than one subscriber for the event.)
So for example in your case
myServer.RfcServerError += new RfcServer.RfcServerErrorEventHandler(ErrorHandler);
But note, that your defintion of the event handler (method ErrorHandler) is wrong! The second argument should be of type RfcServerErrorEventArgs, not RfcServerErrorEventHandler!
public void ErrorHandler(object sender, RfcServerErrorEventArgs e)
{
// Do something with "e" here. Throwing an exception is probably
// not a good idea...
throw new Exception("The method or operation is not implemented.");
}

Stateless state machine library - appropriate way to structure?

How do people structure their code when using the c# stateless library?
https://github.com/nblumhardt/stateless
I'm particularly interested in how this ties in with injected dependencies, and a correct approach of responsibilities and layering correctly.
My current structure involves the following:
public class AccountWf
{
private readonly AspNetUser aspNetUser;
private enum State { Unverified, VerificationRequestSent, Verfied, Registered }
private enum Trigger { VerificationRequest, VerificationComplete, RegistrationComplete }
private readonly StateMachine<State, Trigger> machine;
public AccountWf(AspNetUser aspNetUser, AccountWfService userAccountWfService)
{
this.aspNetUser = aspNetUser;
if (aspNetUser.WorkflowState == null)
{
aspNetUser.WorkflowState = State.Unverified.ToString();
}
machine = new StateMachine<State, Trigger>(
() => (State)Enum.Parse(typeof(State), aspNetUser.WorkflowState),
s => aspNetUser.WorkflowState = s.ToString()
);
machine.Configure(State.Unverified)
.Permit(Trigger.VerificationRequest, State.VerificationRequestSent);
machine.Configure(State.VerificationRequestSent)
.OnEntry(() => userAccountWfService.SendVerificationRequest(aspNetUser))
.PermitReentry(Trigger.VerificationRequest)
.Permit(Trigger.VerificationComplete, State.Verfied);
machine.Configure(State.Verfied)
.Permit(Trigger.RegistrationComplete, State.Registered);
}
public void VerificationRequest()
{
machine.Fire(Trigger.VerificationRequest);
}
public void VerificationComplete()
{
machine.Fire(Trigger.VerificationComplete);
}
public void RegistrationComplete()
{
machine.Fire(Trigger.RegistrationComplete);
}
}
Should we implement all processes (call to services) within the OnEntry hook, or implement the processes on the outside after the state transition has been verified that it is allowed to take place? I'm wonder how to do the transaction management if so.
I guess what I'm after is some best guidance from those who have already implemented something using stateless and how to approach the code structure.
Before addressing the structure itself a couple remarks:
OnEntry actions are only executed if the trigger has been successfully fired.
Triggers fired that are not allowed in the current state will throw an InvalidOperationException. Consider overriding OnUnhandledTrigger if you're not expecting an exception (I've found that logging unhandled triggers is a good approach to finding the flaws in the logic).
My rule of thumb for the OnEntry/OnExit structuring is that any creation and logic will be placed OnEntry and any required clean-up is done OnExit.
So in your case, given that the you're using injected dependencies (and assuming you're not taking ownership of those, i.e, someone else will manage their lifecycle) you can place all your logic OnEntry.
With that in mind, the way that your state machine is currently structured is perfectly fine.
One last note, keep in mind that firing triggers from within the same thread that's advancing the state machine and doing the state machine logic can and will lead to stackoverflow exceptions (see here on how to solve the auto advance issue).

Detect/listen for service start and stop state changes

I have a C# application that uses a Windows service that is not always on and I want to be able to send an email notification when the service starts and when it shuts down. I have the email script written, but I cannot seem to figure out how to detect the service status changes.
I have been reading up on the ServiceController class and I think that the WaitForStatus() method might be what I need, but I haven't been able to find an example with it being used on a service that is not yet started. EDIT: Due to the fact that the WaitForStatus() method busy-waits and I need to be executing the rest of the program run by the service while listening for the service to start/stop, I don't think that this is the method for me, unless someone has a solution that uses this method combined with multithreading and is clean and efficient.
More:
the service will not be started by the application - the application user will be starting that directly from the Services window in the Administrative Tools.
the service used is not a default Windows service - it is a custom service designed for use with this application
Thanks for your help!
P.S. please note that I'm fairly new to C# and am learning as I go here.
UPDATE:
I have managed to get the alert email to send each time the service starts: As I continued to read through the code that I have (which I, unfortunately, cannot post here), I noticed that the class used to create the service was extending the ServiceBase class and that someone made a custom OnStart() method to override the default one. I added the necessary method calls to the new OnStart() method and it successfully sent the notifications.
I attempted to do the same thing for the OnStop() method, but that did not work out so well for me - before I continue, I would like to add that I have been programming in Java for several years, and I am very familiar with Java design patterns.
What I attempted to do, which would have worked in Java, was override the ServiceBase class's OnStop() method with one that calls the email notification, cast MyService to be of type ServiceBase and then re-call the ServiceBase class's Stop() method (NOTE: OnStop() is a protected method so it could not be called directly - the Stop() method calls OnStop() and then continues with the necessary code to stop the service). I thought that casting to type ServiceBase would force the default OnStop() method to be called, instead of my custom one.
As you may imagine, I ended up with just under 10,000 emails successfully sent to my inbox before I managed to force my computer into a hard shutdown.
What I need now is a way to either use my overridden OnStop() method and then have it call the default method, or another solution to this problem. Any and all help is much appreciated. Thanks so much.
FOR THOSE OF YOU WITH MULTITHREADING SOLUTIONS:
protected override void OnStart(string[] args) {
string subject = "Notice: Service Started";
string body = "This message is to notify you that the service " +
"has been started. This message was generated automatically.";
EmailNotification em = new EmailNotification(subject, body);
em.SendNotification();
...INITIALIZE LISTENER FOR SERVICE STOPPING HERE...
...custom stuff to be run on start...
}
Also, remember that the class that this method is called in, let's call it Service, extends the ServiceBase class.
UPDATE TWO:
In regards the suggestion that I use NotifyServerStatusChange I have learned that it is not permitted for the solution to use system functions, due to various reasons. To clarify, only solutions that are purely within the scope of C# and .NET are viable. Thanks, again, for your help!
Here is the solution and why I could not find it before: As I said earlier, my class extended the ServiceBase class. In my first update, I posted that I attempted to solve this in the same way I would have solved it with Java: through casting. However, in C# casting apparently doesn't let you call the base method if you overrode it in the derived class. One of the things that I did not know when I first posted this question and this update (and clearly one of the things that no one thought of) was that C# includes the base constructor that can be used to call methods of the base class from a derived class. As the base constructor can be used for any class in C# it does not appear in the ServiceBase Class documentation.
Once I learned this, I was able to take my original solution and modify it to use the base class:
protected override void OnStop() {
string subject = "Notice: Service Stopped";
string body = "This message is to notify you that the service has " +
"been stopped. This message was generated automatically.";
EmailNotification em = new EmailNotification(subject, body);
em.SendNotification();
base.OnStop();
}
I figured this out when I was playing around with the code in Visual Studio and noticed base in my IntelliSense. I clicked to go to its definition and it sent me to ServiceBase (where it was obviously not defined). After noticing that base was not defined in my code and that it was an instance of the ServiceBase class I realized that it must have been some sort of constructor. After a quick Google search, I found what I was looking for. Way to go IntelliSense!
Thank you everyone for all your help!
If you want a .NET solution with no win32 api then check out my solution below. I'm inheriting from the ServiceController class and using the WaitForStatus() inside of a Task to make it non-blocking then raising events when the status changes. Perhaps it needs more testing but works for me:
CLASS DEFINITION
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using System.ServiceProcess; // not referenced by default
public class ExtendedServiceController: ServiceController
{
public event EventHandler<ServiceStatusEventArgs> StatusChanged;
private Dictionary<ServiceControllerStatus, Task> _tasks = new Dictionary<ServiceControllerStatus, Task>();
new public ServiceControllerStatus Status
{
get
{
base.Refresh();
return base.Status;
}
}
public ExtendedServiceController(string ServiceName): base(ServiceName)
{
foreach (ServiceControllerStatus status in Enum.GetValues(typeof(ServiceControllerStatus)))
{
_tasks.Add(status, null);
}
StartListening();
}
private void StartListening()
{
foreach (ServiceControllerStatus status in Enum.GetValues(typeof(ServiceControllerStatus)))
{
if (this.Status != status && (_tasks[status] == null || _tasks[status].IsCompleted))
{
_tasks[status] = Task.Run(() =>
{
try
{
base.WaitForStatus(status);
OnStatusChanged(new ServiceStatusEventArgs(status));
StartListening();
}
catch
{
// You can either raise another event here with the exception or ignore it since it most likely means the service was uninstalled/lost communication
}
});
}
}
}
protected virtual void OnStatusChanged(ServiceStatusEventArgs e)
{
EventHandler<ServiceStatusEventArgs> handler = StatusChanged;
handler?.Invoke(this, e);
}
}
public class ServiceStatusEventArgs : EventArgs
{
public ServiceControllerStatus Status { get; private set; }
public ServiceStatusEventArgs(ServiceControllerStatus Status)
{
this.Status = Status;
}
}
USAGE
static void Main(string[] args)
{
ExtendedServiceController xServiceController = new ExtendedServiceController("myService");
xServiceController.StatusChanged += xServiceController_StatusChanged;
Console.Read();
// Added bonus since the class inherits from ServiceController, you can use it to control the service as well.
}
// This event handler will catch service status changes externally as well
private static void xServiceController_StatusChanged(object sender, ServiceStatusEventArgs e)
{
Console.WriteLine("Status Changed: " + e.Status);
}
The ServiceController class has a WaitForStatus method. Internally it does polling, though.
If you can't PInvoke NotifyServiceStatusChange, then you'll have to poll the service. For example:
ServiceController sc = new ServiceController("Some Service");
Console.WriteLine("Status = " + sc.Status);
You can use wmi to monitor for events: technet.microsoft.com/en-us/library/ff730927.aspx
Be very carefull with the use of NotifyServiceStatusChange(), because it is only supported on Windows Vista/Windows 2008 (and above). If you target any platforms below, you can't use that API. (There are still lots of XP/Windows 2000-2003 systems out there.)
To make it even worse, polling will not be always reliable in case of service restarts, because if you are polling a service on a very fast system (SSD-drives or pre-buffered I/O on virtual machines), the service might restart between two polls.

IEventAggregator does not reach accross modules

I am trying to get my IEventAggregator to allow me to publish and event in one module and catch it in another. I have tried my code below in a single module/project and it works great. It only fails when I have one module/project publish the event and another subscribe to it.
I have having my IEventAggregator injected into both modules via unity.
I have 3 projects, two of them have modules (call them A and B) and one is just a plain class library (call it Interfaces)
In class library Interfaces there is this code:
public class RandomTestEvent : CompositePresentationEvent<string>
{
}
In module A there is this code in a button click command (this is really in a View Model in the project):
var evt2 = _eventAggregator.GetEvent<RandomTestEvent>();
evt2.Publish("Testing");
In module B there is this code:
public void Initialize()
{
var evt2 = _eventAggregator.GetEvent<RandomTestEvent>();
evt2.Subscribe(OnRandomThingDone);
}
private void OnRandomThingDone(string obj)
{
MessageBox.Show("Random Event Done With: " + obj);
}
I can trace through and I see Subscribe get called. When I look at Publish geting called the debugger says Subscriptions = 1 (so it knows that the subscription was made, so I don't seem to have 2 different instances of IEventAggregator.)
But OnRandomThingDone never gets called after Publish.
Any Ideas why? (Do I need to post more code? If so let me know.)
Really random guess - your subscriber is getting GC'd before the event is published - since the default behavior of Prism's CompositePresentationEvent is to use WeakReferences for preserving subscriber target references.
So...try calling the Subscribe overload which allows you to specify keepSubscriberReferenceAlive and pass in true.
If your subscriber then receives the event successfully, it means that your class which contains OnRandomThingDone is going out of scope and getting GC'd before the event is published.
Random API reference:
http://msdn.microsoft.com/en-us/library/ff921122(PandP.20).aspx
Actually grimcoder is correct, a weak reference requires a public Action method.
Utilizing a week reference relieves the coder of unsubscribing to the event, this is managed by the GC.
You can however use a strong reference by passing true to keepSubscriberReferenceAlive, which also can speed up your program if a large number of events is called in a short period of time.
For more information on this see: Chapter 9: Communicating Between Loosely Coupled Components Section Subscribing Using Strong References
It has nothing to do with GC since once Subsriber is attached reference to it never dies.
The real problem is due to inaccessibility of the OnRandomThingDone
if MUST be public i.e:
**public** void OnRandomThingDone(string obj)
{
MessageBox.Show("Random Event Done With: " + obj);
}

Can a Singleton Class inside a DLL be shared across processes?

I am creating a custom .net hardware framework that will be used by other programmers to control some hardware. They will add a reference to our DLL to get to our hardware framework. I am in need of a shared class that will be accessed from multiple applications (processes).
The singleton pattern seems to be what I need but it only works for multiple threads inside your process. I could be completely wrong but here is an example of the C# code I currently have. I can't help to feel that the design is incorrect. I wish I could share more specific information but I can't.
I must stress that I will have no control over the customer application. The solution must be contained inside the framework (DLL) itself.
The Framework: (Shared DLL)
public class Resources
{
static readonly Resources m_instance = new Resources();
public string Data;
private Resources()
{
Data = DateTime.Now.ToString();
}
public static Resources Instance
{
get
{
return m_instance;
}
}
}
The Test Application: (eventually customer app)
class Program
{
static void Main(string[] args)
{
Console.WriteLine("Press enter to capture the resource!");
Console.ReadLine();
var resources = Resources.Instance;
Console.WriteLine("\r\n{0}: {1}\r\n", Thread.CurrentThread.ManagedThreadId, resources.Data);
BackgroundWorker worker = new BackgroundWorker();
worker.DoWork += WorkerDoWork;
worker.RunWorkerAsync();
while (worker.IsBusy)
{
Thread.Sleep(100);
}
Console.WriteLine("Press enter to close the process!");
Console.ReadLine();
}
static void WorkerDoWork(object sender, DoWorkEventArgs e)
{
var resources = Resources.Instance;
Console.WriteLine("\r\n{0}: {1}\r\n", Thread.CurrentThread.ManagedThreadId, resources.Data);
}
}
The first launched application gives an output of:
Press enter to capture the resource!
1: 6/24/2009 8:27:34 AM
3: 6/24/2009 8:27:34 AM
Press enter to close the process!
The second application gives an output of:
Press enter to capture the resource!
9: 6/24/2009 8:27:35 AM
10: 6/24/2009 8:27:35 AM
Press enter to close the process!
Conclusion:
I would like to see both applications return the same string of the time of the first instantiation of the class.
As you can see the singleton works for the multiple thread inside the process but not cross processes. Maybe this can't be done for I can't seem to find any solution.
Yes it is possible to share a singleton amongst several processes. However you will need to take advantage of a technology which supports interprocess communication in order to achieve this result.
The most popular technologies which allow you to share out your object fairly directly are Remoting and WCF.
Giving an example of sharing a singleton with either of these is beyond the scope of an SO answer. But there are many tutorials on the web for each of these. Googling either technology plus singleton should put you on the right path.
You cannot use a singleton to sync across applications. Each runs in its own application space, and as a matter of security cannot access memory/objects/etc. from the other without a method of communication (like remoting) To sync the two they would have to remote into a third program.
To add to the Kevin's answer, your constructor for your class Resources should really be made private for it to be a true singleton, otherwise nothing is stopping someone from creating a new instance of the Resources class through the constructor. This doesn't solve your problem, but it does stop one from misusing the Singleton.
Simply calling a singleton property in a different assembly from two different processes will create different instances of that class.
But you can easily share information between processes using .Net Remoting, or fire interprocess events if you only need simple signaling (EventWaitHandle).
[Edit:] To make it look like a Singleton to your callers, you can expose a class which will internally use Remoting to instantiate a singleton, and then return the instance transparently. Here is an example which (I think) does that: http://www.codeproject.com/KB/dotnet/remotingsingleton.aspx
There are ways to do it as mentioned above. But it is clumsy if you use WCF or remoting. Please try interprocess thread sync techniques.
For more info read the online free e-book on threading
http://www.albahari.com/threading/
Specially see the cross process sync constructs here ...
http://www.albahari.com/threading/part2.aspx#_Synchronization_Essentials

Categories