2

I am completely new to async/await and have been "improving" a totally synchronous app I wrote two years ago. I have the following situation that I am unhappy with my solution.

The XAML is bound to the following two classes:

XAML

private InsuranceEditor _primaryinsurance;
public InsuranceEditor PrimaryInsurance
{
      get { return _primaryinsurance; }
      set { if (_primaryinsurance == value) return; _primaryinsurance = value; OnPropertyChanged("PrimaryInsurance"); }
}

private InsuranceEditor _secondaryinsurance;
public InsuranceEditor SecondaryInsurance
{
       get { return _secondaryinsurance; }
       set { if (_secondaryinsurance == value) return; _secondaryinsurance = value; OnPropertyChanged("SecondaryInsurance"); }
}

The classes, PrimaryInsurance, and SecondaryInsurance inherit from the abstract class Insurance:

abstract class InsuranceEditor : SimpleViewModelBase, ISave, IDataErrorInfo
{
           .................
           // Constructor
    public InsuranceEditor(PatientDemographicsEditor patient, Billing service)
    {
        ...
    } 

Factory pattern used for asynchronous construction of PrimaryInsurance (Async OOP Constructor)

private async Task<PrimaryInsurance> InitializeAsync()
{
    // asyncData = await GetDataAsync();
    return this;
}

public static Task<PrimaryInsurance> Create(PatientDemographicsEditor patient, Billing service)
{
    var ret = new PrimaryInsurance(patient, service);
    return ret.InitializeAsync();
}

// Constructor 
private PrimaryInsurance(PatientDemographicsEditor patient, Billing service)
    : base(patient, service)
{
    Editor_Id = 1;
     ........
}

class SecondaryInsurance : InsuranceEditor
{
    // Constructor
    private SecondaryInsurance(PatientDemographicsEditor patient, Billing service)
        : base(patient, service)
    {
        Editor_Id = 2;
      ............................
    }
}

Logically, both primary and secondary insurance only differ in their Editor_Id, so it seemed natural to inherit from a common InsuranceEditor. The problem now comes with "correctly" applying async/await to the Primary and Secondary Insurance. I would like usage to be something like:

PrimaryInsurance = await PrimaryInsurance.Create(....) where Create(...) is recognized as a static method of PrimaryInsurance (not necessarily a static method of the abstract class InsuranceEditor.)

Can this be done?

Edit #1. After posting this question, I'm thinking it may have already been asked, What's the correct alternative to static method inheritance? and that what I want can't be done in C#. Is this correct?

Edit #2: The problem I am having in VS comes with the usage statement:

PrimaryInsurance = await PrimaryInsurance.Create(Patient, BILLING);

VS tells me that:

Member 'InsuranceEditor.Create(PatientDemographicsEditor, Billing)' cannot be accessed with an instance reference; qualify it with a type name instead

And then if I allow VS to make the Create(...) (so that there are no errors), it makes this in the abstact InsuranceEditor class, not the PrimaryInsurance Class.

internal Task<InsuranceEditor> Create(PatientDemographicsEditor patient, Billing bILLING)
        {
            throw new NotImplementedException();
        }

What am I doing wrong?

Community
  • 1
  • 1
Alan Wayne
  • 5,122
  • 10
  • 52
  • 95
  • If all they differ is the `Editor_Id` why not just use one class and pass in the Editor_Id as a parameter to a private constructor? Then you just do `await InsuranceEditor.CreatePrimary(...)` or `await InsuranceEditor.CreateSecondary(...)` – Scott Chamberlain Jul 01 '16 at 19:00
  • @ScottChamberlain That's exactly what occurred to me after writing the question. But I can see other cases where it would be more difficult, so am hoping for some ideas on how inheritance could be used in this case with a static Create on the child class. – Alan Wayne Jul 01 '16 at 19:05
  • 2
    I am not really sure what your question in this is. You ask "can it be done" but it looks like you have a working example in your question. What exactly is your question? – Scott Chamberlain Jul 01 '16 at 19:11
  • @ScottChamberlain Well...not quit working. In the usage statement, "await PrimaryInsurance.Create(...)", VS insists on PrimaryInsurance first being instantiated and it is placing the Create() in the abstract InsuranceEditor class. Hence, PrimaryInsurance.Create() needs to be InsuranceEditor.Create()...not what I was hoping for. – Alan Wayne Jul 01 '16 at 23:06
  • I don't understand your reply to Scott's question. What do you mean by "instantiated"? In what way is VS "insisting" on this "instantiation"? In what way is VS requiring that the `Create()` method be declared in the base class? I see no reason it should. Of course, since your question lacks a good [mcve], it's impossible to really understand how you code is structured now, never mind what you'd like it to look like instead. Please improve the question to clarify these points. – Peter Duniho Jul 02 '16 at 01:16
  • So you want your abstract base class to also be a factory class for the child classes? – JamesFaix Jul 02 '16 at 01:20
  • @PeterDuniho Please see new edit. How to I get VS to see Create() from the child class PrimaryInsurance so that PrimaryInsurance.Create() is valid? Thanks. – Alan Wayne Jul 02 '16 at 04:13
  • @JamesFaix (with further Google), it appears so. Thanks. – Alan Wayne Jul 02 '16 at 04:20
  • 1
    Static members must always be called on the type they are declared in, not child types. So if you would want to call `BaseClass.Create()` not just `Create()`. With instance methods you can call `Create()` in the child class because it is also an instance of `BaseClass` and so it has the same public and protected instance members available, but the static members are bound to the type (think of a `Type` object kinda) not the instances of that type. – JamesFaix Jul 02 '16 at 13:57
  • @JamesFaix Great explanation! Thanks. – Alan Wayne Jul 02 '16 at 18:36
  • 1
    @JamesFaix: _"Static members must always be called on the type they are declared in, not child types"_ -- that is not true. E.g. given `class A { public static void M() { } }` and `class B : A { }`, you can call `B.M();`. The `M()` method declared in `A` absolutely is a valid _static_ member of `B` and can be referred to as such. – Peter Duniho Jul 02 '16 at 19:07

1 Answers1

2

You still haven't provided a good Minimal, Complete, and Verifiable code example that reliably reproduces the problem. But based on the example program statement and the error message you've quoted, it appears that you are trying to use the PrimaryInsurance identifier in a context where it is ambiguous with the name of a property.

If you want to keep the name of the property, then anywhere you want to use the type name, you'll need to fully qualify it. For example:

PrimaryInsurance = await MyNamespace.PrimaryInsurance.Create(Patient, BILLING);

where MyNamespace is whatever the actual namespace is for the type.

If the namespace is especially long, or for any other reason you would prefer to not have to type the whole thing out every time, you can alias the type name with a using directive. For example:

using PrimaryInsuranceType = MyNamespace.PrimaryInsurance;

Then your program statement could look like this:

PrimaryInsurance = await PrimaryInsuranceType.Create(Patient, BILLING);

Of course, PrimaryInsuranceType is just an example. You can use whatever type alias name you want, as long as it's different from the property name itself (or any other property name in the class).

Peter Duniho
  • 68,759
  • 7
  • 102
  • 136
  • Thanks. That did it. – Alan Wayne Jul 02 '16 at 05:44
  • I have read "Minimal, Complete, and ...." about a hundred times now. I clearly am not getting it (as I thought I did so on this question). A few good examples of "Minimal...." would be most helpful. – Alan Wayne Jul 02 '16 at 05:46
  • 1
    @Alan: I'm not sure how to explain it better than at the [mcve] and [ask] pages. I can tell you how your question fails to meet the bar: it is not possible to simply copy/paste the code you posted and, without any changes to it, attempt to compile the code to reproduce the problem you reported. Make sure you read the articles at the links at the end of the [ask] page. Bonus points for reading http://sscce.org/ as well (yet another resource to help people understand the critically important need to provide good code examples when asking questions). – Peter Duniho Jul 02 '16 at 06:23
  • Thank you very much for the critique--I am still learning. (It would be great if more reviewers would follow your example!) Thanks (the link to sscce.org and where I went wrong is most helpful). – Alan Wayne Jul 02 '16 at 18:34