Mike
Mike

Reputation: 5509

Is this a good way to handle unique properties for a generic?

I have a generic class that represents a document that can be of currently only two types. Type1 or Type2. Most of the methods and properties work perfectly for both types but the title is different. What I am wondering is if there is a better way to handle this? Thanks!!

[XmlIgnore]
public string DocumentType
{
  get
  {
    return typeof(T).Name;
  }
}

[XmlIgnore]
public string DocumentTitle
{
  get
  {
    string retval = string.Empty;
    Object obj = Document;

    switch (DocumentType)
    {
      case "Type1":
        retval = ((Type1)obj).title.Text;
        break;
      case "Type2":
        retval = ((Type2)obj).Title;
        break;
    }
    return retval;
  }
}

Type1 and Type2 were generated using xsd.exe so I hesitate to change them although maybe adding a readonly xml ignored property to get the title in both Type1 and Type2 that is consistent?

Upvotes: 3

Views: 105

Answers (3)

fejesjoco
fejesjoco

Reputation: 11903

XSD's can also handle inheritance. Define the base complexType (possibly with abstract="true") then create 2 complexType's which extend the base one. If you generate code from it, it will also reflect this inheritance.

Upvotes: 0

Toby
Toby

Reputation: 7544

Does xsd.exe generate partial classes? If so, Mike's answer is cleaner than this one. (Create a new partial class code file for each of your type classes and implement the interface in the non-generated files.)

Otherwise, so as not to be modifying generated code, I'd recommend you use safe-casting to determine the document type:

    public string ExtractDocumentTitle()
    {
        Type1 t1 = Document as Type1;
        if (t1 != null)
            return t1.title.Text;

        Type2 t2 = Document as Type2;
        if (t2 != null)
            return t2.Title;


        // fall-through & catch-all
        return String.Empty;
    }

Upvotes: 1

Mark Byers
Mark Byers

Reputation: 838256

Use a common interface and implement it in each class. If you don't want to change the original class you could try adding a wrapper around each class that implements this interface.

interface IHasTitle
{
    string Title { get; }
}

class MyType1 : Type1, IHasTitle
{
    // Add constructors here.

    public string Title { get { return this.title.Text; } }
}

class MyType2 : Type2, IHasTitle
{
    // Add constructors here.
}

Then you can do this:

[XmlIgnore]
public string DocumentTitle
{
    get
    {
        IHasTitle hasTitle = Document;
        return hasTitle.Title;
    }
}

You might want to extend the interface to IDocument and include all the other common members such as Name, etc.

Upvotes: 3

Related Questions