Search code examples
c#genericsdesign-patternsinterfaceabstraction

Need help deciding how to structure a C# application that creates products that share similarities but have their differences


I'm having a bit of a mental block trying to figure out the best architecture for this program and need some help.

I'm writing a C# application that creates what we'll call "Views". A view is basically an object which accepts some data as input and spits out another object as output.

Here is the code I'm envisioning:

ViewResponse response;
ViewRequest request;

request = new CustomerViewRequest();
request.Translations = GetTranslations(); // generic to Request
request.CustomerViewAsOfDate = new DateTime(2014,1,1); // specific to CustomerViewRequest

response = ViewCreator.CreateView(request);
Console.WriteLine(response.ViewCreatedSuccessfully); // generic to Response
Console.WriteLine((CustomerViewResponse)response.SomeCustomerViewSpecificProperty); // specific to CustomerViewResponse

request = new BKLedgerViewRequest();
request.Translations = GetTranslations(); // generic to Request
request.EAAnalysisData = GetEAAnalysisData(); // specific to BKLedgerViewRequest

response = ViewCreator.CreateView(bkRequest);
Console.WriteLine(response.ViewCreatedSuccessfully); // generic to Response
Console.WriteLine((BKLedgerViewResponse)response.SomeBKLedgerViewSpecificProperty); // specific to BKLedgerViewResponse

Solution

  • As I look at your code, it seems like the key to accomplishing what you want is just to understand object-oriented coding, inheritance, covariance, and contravariance. I did a re-factor of your code below that compiles and generally does what you are looking for based on using a base class for ViewRequest and ViewResponse.

    When you instantiate the objects, using the more specific types of CustomerViewRequest (for example) gives you an object that you can treat as either a ViewRequest or a CustomerViewRequest, depending on your needs.

    class Class6
    {
        public object GetTranslations() { return null; }
        public object GetEAAnalysisData() { return null; }
    
        public void DoStuff()
        {
            CustomerViewRequest cvRequest = new CustomerViewRequest();
            cvRequest.Translations = GetTranslations(); // generic to Request
            cvRequest.CustomerViewAsOfDate = new DateTime(2014, 1, 1); // specific to CustomerViewRequest
    
            CustomerViewResponse cvResponse = ViewCreator.CreateViewResponse<CustomerViewResponse>(cvRequest);
            Console.WriteLine(cvResponse.ViewResponseCreatedSuccessfully); // generic to Response
            Console.WriteLine(cvResponse.SomeCustomerViewSpecificProperty); // specific to CustomerViewResponse
    
            BKLedgerViewRequest bkRequest = new BKLedgerViewRequest();
            bkRequest.Translations = GetTranslations(); // generic to Request
            bkRequest.EAAnalysisData = GetEAAnalysisData(); // specific to BKLedgerViewRequest
    
            BKLedgerViewResponse bkResponse = ViewCreator.CreateViewResponse<BKLedgerViewResponse>(bkRequest);
            Console.WriteLine(bkResponse.ViewResponseCreatedSuccessfully); // generic to Response
            Console.WriteLine(bkResponse.SomeBKLedgerViewSpecificProperty); // specific to BKLedgerViewResponse
        }
    }
    
    class ViewRequest
    {
        public object Translations { get; set; }
    
    }
    class ViewResponse
    {
        public bool ViewResponseCreatedSuccessfully { get; set; }
    }
    class CustomerViewRequest : ViewRequest
    {
        public DateTime CustomerViewAsOfDate { get; set; }
    }
    
    class CustomerViewResponse : ViewResponse
    {
        public string SomeCustomerViewSpecificProperty { get; set; }
    }
    
    static class ViewCreator
    {
        public static T CreateViewResponse<T>(ViewRequest request)
            where T : ViewResponse, new()
        {
            return new T();
        }
    }
    class BKLedgerViewResponse : ViewResponse
    {
        public int SomeBKLedgerViewSpecificProperty { get; set; }
    }
    
    class BKLedgerViewRequest : ViewRequest
    {
        public object EAAnalysisData { get; set; }
    }