Reputation: 67960
I have the following code:
/// <summary>
/// BrowserFactory responsible for deciding if you should receive a shared or isolated browser instance.
/// </summary>
public static class BrowserFactory
{
/// <summary>
/// Shared Browser Instance
/// </summary>
private static SharedBrowser _sharedBrowser;
/// <summary>
/// The window handle of the shared browser instance.
/// </summary>
private static string _sharedHwnd;
/// <summary>
/// The last thread id to access the shared browser.
/// </summary>
private static int _sharedThreadId;
static BrowserFactory()
{
Shared= new SharedBrowser();
}
private static SharedBrowser Shared
{
get
{
var currentThreadId = GetCurrentThreadId();
if (currentThreadId != _sharedThreadId)
{
_sharedBrowser = IE.AttachTo<SharedBrowser>(Find.By("hwnd", _sharedHwnd));
_sharedThreadId = currentThreadId;
}
return _sharedBrowser;
}
set
{
_sharedBrowser = value;
_sharedHwnd = _sharedBrowser.hWnd.ToString();
_sharedThreadId = GetCurrentThreadId();
}
}
public static Browser GetBrowser()
{
return BrowserSettings.UseSharedBrowser ? Shared : new Browser();
}
}
How can I make it so I only instantiate the SharedBrowser object when the property is first accessed rather than in the constructor?
At first I thought to do it in the Shared property, but it seemed weird to be calling the a set from a properties get.
I also thought about having the _sharedBrowser be wrapped around in a .NET 4.0 Lazy object but then I'm not sure how to directly instantiate something wrapped in Lazy which is what I would need to do in the Shared property when a user gets (after the re-attaching).
I don't see how I could this without duplicating my Shared properties .set logic in the .get.
Any ideas?
Upvotes: 0
Views: 152
Reputation: 112344
You can use this pattern for static as well as for instance members:
private SomeType _myProperty;
public SomeType MyProperty
{
get
{
if (_myProperty == null) {
_myProperty = new SomeType();
}
return _myProperty;
}
}
This is called lazy instantiation.
EDIT:
private static SharedBrowser _shared;
public static SharedBrowser Shared {
get
{
var currentThreadId = GetCurrentThreadId();
if _shared == null) {
_shared = new SharedBrowser();
_sharedHwnd = _sharedBrowser.hWnd.ToString();
_sharedThreadId = currentThreadId;
}
if (currentThreadId != _sharedThreadId) {
_sharedBrowser = IE.AttachTo<SharedBrowser>(Find.By("hwnd", _sharedHwnd));
_sharedThreadId = currentThreadId;
}
return _shared;
}
}
Upvotes: 1
Reputation: 25684
Store a private class level SharedBrowser variable, then check if its null in your get block. Then to complete your extra initialization logic, refactor that into another method and call it from both the get
and the set
.
private static SharedBrowser _shared = null;
private static SharedBrowser Shared
{
get
{
if(_shared == null)
{
_shared = new SharedBrowser();
InitSharedBrowser();
}
// the rest of your code here.
}
set
{
_shared = value;
InitSharedBrowser();
}
}
private static void InitSharedBrowser()
{
// your SharedBrowser Initialization logic goes here.
}
Upvotes: 0
Reputation: 19765
The nice thing about a static constructor is you know it will be called only once per application. You don't have that kind of guarantee later on. So add a static constructor and wrap your instantiation in a Lazy < T > in it, and then reference the Lazy's .Value in your .get
Upvotes: 0