StephenCleary / CrossDomainSingleton

An AppDomain-aware, thread-safe singleton that ensures only one instance exists in the entire application.
MIT License
21 stars 8 forks source link

Found issue while using CrossDomainSingleton in xUnitTest. #1

Open monze opened 5 years ago

monze commented 5 years ago

Hey

Found your project, and was very happy, as the concept fit right into the need of my project - and the test project work perfectly, I included the classes in my project, however when I started the xUnitTest, things stating to broke down. First, the default AppDomain can't be located. Fix that without using Lazy instances (I thing..?). The next problem is that the default appDomain is "testhost.x86.exe", and located under C:/Program Files/VisualStudio[something]/ which can't create the desired singleton type - as it is unknown in that domain.

Then, did a simple test, and if the default domain is testHost.x86.exe, then defaulted back to current domain, but then this make this method break

        private static void CreateCallback()
        {
            var _ = LazyInstance.Value;
        }

with exception 'ValueFactory attempted to access the Value property of this instance.'. The Internet says it is a VS problem - but I don't know.

So after the 3. issue, I stop and start thinking - There is clearly something wrong with our implementation. The idea is brilliant, but the implementation has some problems.

My use case is, that the CrossDomainSingleton should handle my LoggerManager instance, which is included in almost all classes (and in multi AppDomain). So It should also work though xUnitTest, sometimes across domains.

The problem is we can't get around unitTesting - which used the default AppDomain, and it must work in production (now in the default AppDomain).

Idea: In each unit test, set -> AppDomain.CurrentDomain.SetData("unitTest", true); Now to find the 'default' appDomain, go up though parent domain, until default or the 'unitTest' is found and is true. Or simply, check parent domain until it name is "testhost.x86.exe" (or whatever name of the test framework that is used).

What do you thing is the best way to move forward?

Jacob Mogensen

StephenCleary commented 5 years ago

This is just some example code. I never even used it in production.

That said, I'm open to finding a solution for this. I think the special app domain name may make the most sense. This repo takes PRs. :)

monze commented 5 years ago

Thanks for you replay.

I have never made a PR before, so I tried ... and failed. I ended up branching you code to my own site here: https://github.com/monze/CrossDomainSingleton After that, I just made the change there.

I can't find a relation between child and parent AppDoman, so in the end, I decided to add my own. Basically, the implementation does not guaranties singleton (as designed) because this will break in unitTesting. However, as long as one line is included when an AppDomain is created, everything works fine.

subAppDomain.SetData(AppDomainHelper.KeyParentAppDomainFrindlyName, AppDomain.CurrentDomain.FriendlyName);

The basic idea is, that we are not interested in how many domains there actually exist in execution of the code - as long as we can guarantee that all of our code (and every subDomain we create) works. When we create a sub AppDomain, we do it our way to make our Singleton work, and all of our code to works. So this idea is, that there can be created multi 'Singleton' instance, each in different unitTest execution, without interfering with each other - it sounds weird, but is it not that exact behavior we want?

I don't have a public profile on the Internet, so if you can/will take ownership of the code (in the end) I will be happy.

Jacob Mogensen