简体   繁体   中英

C# Generic factory method does not call constructor as intended

So I have a type inherited from Page (2nd descendant: CreationDialog : MainPage : Page ) with a parameterless constructor. I have a static generic factory method in the PageFactory class:

public static class PageFactory
{
    public static T GetInstance<T>(WebDriver driver) where T : Page, new()
    {

        T page = new T
        {
            Driver = driver
        };
        return page;
    }
}

public class Page 
{
public static T GetInstance<T>() where T : Page, new()
    {
        return PageFactory.GetInstance<T>(Utils.GetCurrentDriver());
    }
}

public class CreationDialog : MainPage, IModal
{
   public CreationDialog()
    {
        IModal _Modal = Modal.Get(WindowLocator);
    }

    IModal _Modal { get; set; }
}

Modal.Get(WindowLocator) is a static method with a static parameter.

The problem is - when I call GetInstance<CreationDialog>() I end up not initializing _Modal and a null reference exception when methods from _Modal are called later.

The debugger shows that when get instance is called the type parameter is correcly CreationDialog , so why doesn't it call its own constructor? What am I missing?

Update: a breakpoint in CreationDialog constructor is reached, but after the constructor is left back to method scope page variable is set to null and it is initialized with just the driver .

And who can I read on the subject as I can't seem to get constructors and inheritance right?

The problem is local versus member scope. Change this:

public class CreationDialog : MainPage, IModal
{
    public CreationDialog()
    {
        IModal _Modal = Modal.Get(WindowLocator);
    }

    IModal _Modal { get; set; }
}

To this:

public class CreationDialog : MainPage, IModal
{
    public CreationDialog()
    {
        _Modal = Modal.Get(WindowLocator);  //Don't declare new variable
    }

    IModal _Modal { get; set; }
}

Although this would be even better:

public class CreationDialog : MainPage, IModal
{
    protected readonly IModal _modal;

    public CreationDialog()
    {
        _modal = Modal.Get(WindowLocator);  //Don't declare new variable
    }

    public IModal Modal
    {
        get { return _modal; }
    }
}

You're declaring _Modal twice, once as a local variable and once as a property. You're assigning a value to the variable, to set the value of your property simply remove the type declaration.

public class CreationDialog : MainPage, IModal
{
    public CreationDialog()
    {
        _Modal = Modal.Get(WindowLocator);
    }

    IModal _Modal { get; set; }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM