Reputation: 12925
I'm trying to maximize my code reuse here. I have a SearchQueryDto
with fields like the below:
public class SearchQueryDto{
// some other properties
public string SearchUsername { get; set; } // repetition 1
public string SearchProfile { get; set; } // repetition 1
public SearchInterest SearchInterest { get; set; } // repetition 1
// some other properties
}
Then, I have a database model for Broadcast
with the following:
public class Broadcast {
// some other different properties
public string SearchUsername { get; set; } // repetition 1
public string SearchProfile { get; set; } // repetition 1
public SearchInterest SearchInterest { get; set; } // repetition 1
// some other different properties
public Status Status {get; set;} // repetition 2
public DateTime DateStarted {get; set;} // repetition 2
}
Then, I have a database model for BroadcastMessage
with the following:
public class BroadcastMessage {
// some other properties
public Status Status {get; set;} // repetition 2
public DateTime DateStarted {get; set;} // repetition 2
}
As it stands, adding new search criteria means I have to go and add fields to both my database model Broadcast
AND the DTO. How can I share properties between two classes? Inheritance doesn't seem to be the answer because I might end up sharing properties between Broadcast
and some other type as well.
I'm looking for something simple, like:
// handles repetition 1
public class SearchCriteria{
public string SearchUsername { get; set; }
public string SearchProfile { get; set; }
public SearchInterest SearchInterest { get; set; }
}
// handles repetition 2
public class StatusProperties{
public Status Status {get; set;}
public DateTime DateStarted {get; set;}
}
public class SearchQueryDto: SearchCriteria{
// some other properties
}
public class Broadcast : SearchCriteria, StatusProperties{ // multiple inheritance :(
// some other different properties
}
public class BroadcastMessage : StatusProperties{
// some other properties
}
I don't think inheritance will work because of Broadcast
needs, and I don't think interfaces will work because then I've taken a step in the wrong direction - updating n+1
things instead of just n
things for the convenience of compiler enforcing the inheritance (not the convenience I'm looking for).
I also don't want to hide these properties behind an instantiation of another class for reasons that I think are out-of-scope here.
Upvotes: 2
Views: 3513
Reputation: 2883
I am not a huge fan of using a shared container class or inheritance because this brings the model, DTO objects, ViewModels and other separated classes too much together in my opinion.
I think it's the best solution to implement the properties in each class.
But I think it would be no problem to use an interface to avoid a forgotten property.
public interface IBroadcastMessage{
public Status Status {get; set;}
public DateTime DateStarted {get; set;}
}
public class Broadcast : IBroadcastMessage, ISearchQueryDto { /* ... */ }
public class BroadcastMessage : IBroadcastMessage { /* ... */ }
This does not help to avoid similar code, quite the opposite you must write all you're properties once more. But if you implement it in the interface you cannot forget to implement it in all classes.
Interfaces like these can be helpful on other places too. e.g. for passing an IBroadcastMessage
and don't care which exact type it is.
In this case, what about a refactoring? Why adding a property for each new criteria if you can create a base class which can filter items depending on inherited implementations and add them to a list? Just an idea.
Upvotes: 2
Reputation: 281
Create an object that both classes have instances of. An update to the SearchCriteria updates the properties in both of those classes. Your two classes (broadcast and profilesearchdto) remain decoupled.
SearchCriteria{
public string SearchUsername { get; set; }
public string SearchProfile { get; set; }
public SearchInterest SearchInterest { get; set; }
}
public class ProfileSearchDto {
public SearchCriteria searchCriteria {get; set;}
}
public class Broadcast {
public SearchCriteria searchCriteria {get; set;}
}
Upvotes: 1