I'm writing a library in C# that is meant to abstract calls from a third-party API, such that it can accept inputs from multiple potential applications. Currently, I have three broad classes:
Base
class: authentication, request formatting, foundational data retrieval for any API requestsReader
class: data retrieval that is NOT foundational - "nice to haves", or important abstractions outside of object creationWriter
class: any sort of a "push" to the API, i.e. updating information on their side in some way - many of these calls return important values in addition to the expected "pass/fail" information
The API itself is RESTful, and as such has no explicit differentiation between reads and writes - rather it just denotes which HTTP verb a request uses. I broke my design up into base/reader/writer as it made it clearer for me which abstractions did what, as they extend what is defined in the API.
Now, I have an issue. The data defined in the base class can typically be considered "session-level". There are situations where it would be very helpful to share it between the reader and writer. Currently I have an ugly-looking "memberwise clone" to do this. I didn't use the built-in as there are certain properties that I am intentionally omitting.
Is there a better way to do this? Any other criticisms of my design are certainly welcome as well - I am getting some code smells here.
.......
EDIT AFTER INITIAL COMMENTS:
To answer John - in many situations I need to copy more than 3-4 values so that reads and writes can be routed to the same place, as they are both occurring in the same "session".
The Base
class holds a pool of properties to properly store any incoming values - typically some, but not all, are used. That is why I called my "cloning" ugly.
A simple reason I made the clone was that I have a Base
constructor that generates a token for API requests, and also instantiates a class-level HttpClient
. If I create a Writer
from a Reader
, I don't want to recreate the token and HttpClient
- I want to use what is already there, so I created a new constructor for that purpose.
Regarding your comment on inheritance Flater, I would agree - I just wanted to ensure the derived classes had certain methods and properties. Since I needed both, an interface wasn't an option. The issue could be summarized as poor design and the need for the aforementioned cloning method - in the end, it may be better to eschew it and just copy on the fly as John suggested. I just want to avoid a Reader
needing a Writer
instance for that and vice-versa.
I'll see what I can do about posting code, but the API is a paid product, and my code is pretty closely abstracted around their conventions. If you have ideas on how I can post a concrete example with those restrictions, I'm all ears.
protected
members. What do you need the ugly-looking memberwise clone for?Foo
andBar
derive from the sameBase
class does not mean that an instance ofFoo
and an instance ofBar
somehow share the sameBase
values. Different instances have their own encapsulation.