views:

48

answers:

1

I'm attempting to use the Repository Pattern to write a data access layer on an existing DB2 schema. This schema has several aggregates all having a common base entity of a "Document." When building the business objects, I created the Document entity as an abstract, and the aggregates as entities derived from Document. For example:

public abstract class Document
{
    public long Id{ get; set; }
    public int PageCount{ get; set; }
    public string Path{ get; set; }
}

public class LegalDocument : Document
{
    public int CaseNumber{ get; set; }
}

public class BillingDocument : Document
{
    public int InvoiceNumber{ get; set; }
    public double AmountDue{ get; set; }
}

Now, I want to create a Repository for BillingDocument, but I know that I don't want to load up all of the Document base properties in my BillingDocument repository, so I've created another abstract class with a generic type parameter for this functionality. However, I'm having coder's block figuring out how to return an instance of the abstract Document entity, which will be used by Repositories I will code for the derived aggregate entities. I can do it with reflection, as follows, but it feels all wrong.

abstract class DocumentRepositoryBase<TDocument>
{
    internal Document LoadDocumentBaseProperties(long documentId)
    {
        //Call the database and get the base properties and add them to....this?
        var documentBase = 
            (Document)typeof(TDocument).GetConstructor(Type.EmptyTypes).Invoke(null);
        //Set the documentBase properties
        return documentBase;
    }
}

I'm all twisted up. Can someone please assure me that this is OK, or tell me I'm an idiot and show me a better way?

Thanks in advance.

+2  A: 

Consider using a generic constraint in your repository type, like so:

abstract class DocumentRepositoryBase<TDocument>
  // requires it to be a document derivative and have default constructor
  where TDocument : Document, new() 
{
  internal Document LoadDocumentBaseProperties( long documentId )
  {
     var doc = new TDocument();
     return doc;
  }
}

By the way, this is not returning an instance of an abstract class ... it returns an instances of whatever TDocument may be (one of the derivatives) but via a reference to the base Document type.

LBushkin
That's it. God, thanks, I couldn't think of that for the life of me.
AJ