How should I abstract a collection of objects owned by another object? - c#

In a system for managing vocational training, I have a CourseBase abstract class, which I decided on using in favour of an ICourse interface because I'd prefer to avoid duplicating implementation code for all classes derived from the hypothetical, base Course entity. Each course has a list if subjects, with any subject defined by a SubjectBase abstract class. So, I have e.g.
public abstract class CourseBase : BaseObject
{
public IEnumerable<SubjectBase> Subjects
{
get { return new List<SubjectBase>(); }
}
}
public abstract class SubjectBase
{
public string Name { get; set; }
public string Description { get; set; }
public int ValidityPeriod { get; set; }
}
Now I want to add a concrete class, LocalCourse, which contains a collection of LocalCourseSubject objects, but because I'm not using an interface for CourseBase, I lose out on covariance, and I need to hide the abstract base's Subjects property with my new:
public class LocalCourse: CourseBase
{
public IEnumerable<LocalCourseSubject> Subjects
{
get { throw new NotImplementedException(); }
}
}
I'm sure I'm missing something very obvious here from an OO point of view, but the only solutions I can see are:
Completely omit Subjects from the abstract base, and only add a specifically typed collection property to derived classes.
Implement an interface such as ISubjectCollectionOwner in the abstract base as well as concrete classes.
Please excuse my dimness here, it's been a while since I've had the pleasure of encountering a design issue like this.

Why just not introduce a generic interface to abstract a Course? Sorry if I missed something obvious
public interface ICourse<TSubject>
{
IEnumerable<TSubject> Subjects { get; }
}
public abstract class CourseBase<TSubject>
: BaseObject,
ICourse<TSubject>
{
public IEnumerable<TSubject> Subjects
{
get { return new List<TSubject>(); }
}
}
public class LocalCourse
: CourseBase<LocalCourseSubject>
{
}
If Subject is a vital part of Course entity you should keep it within both ICourse and CourseBase as well, otherwise I would suggects abstracting it by ISubjectAware interface

Can't you just do this:
public abstract class CourseBase<T> where T : SubjectBase
{
public virtual IEnumerable<T> Subjects
{
get { return new List<T>(); }
}
}
public abstract class SubjectBase
{
public string Name { get; set; }
public string Description { get; set; }
public int ValidityPeriod { get; set; }
}
public class LocalCourse : CourseBase<LocalCourseSubject>
{
public override IEnumerable<LocalCourseSubject> Subjects
{
get { throw new NotImplementedException(); }
}
}
I think that would accomplish your short term goal, at any rate, assuming that the general pattern is that each CourseBase inheritor will have a collection of the same type of SubjectBase inheritor. But, if that is the case, this seems like a parallel inheritance hierarchy, which can sometimes be a code smell (not saying that it necessarily is -- I don't know all the details of the domain you're modeling).

Related

Change instance of abstract class that use generics

I am trying to replace derived instances in base class. It works for animals (simple usage of abstract class), but not with generics. The error is in SomeMethod. Is there any clean solution?
EDIT: With help of another interface it is truly doable. Code that is commented with [S] is solution for my original question.
public abstract class Animal
{
public void Feed()
{
}
}
public class Tiger:Animal
{
}
public class Dog : Animal
{
}
public class Consumer
{
public Tiger Tiger { get; set; }
public Dog Dog { get; set; }
public Animal FavoriteAnimal { get; set; }
void SomeMethod()
{
// This is fine
FavoriteAnimal = Tiger;
FavoriteAnimal = Dog;
FavoriteAnimal.Feed();
//Also fine
int numberOfDogs = PlaceForDogs.CountAnimals();
int numberOfTigers = PlaceForTigers.CountAnimals();
//[S] This is doable now
FavoritePlaceForAnimals = PlaceForDogs;//[S] no more ERROR
int numberOfAnimalsOnMyFavoritPlace = FavoritePlaceForAnimals.CountAnimals(); // No error, but I do not get here...
}
public PlaceForDogs PlaceForDogs { get; set; } = new PlaceForDogs();
public PlaceForTigers PlaceForTigers { get; set; } = new PlaceForTigers();
//public PlaceForAnimals<Animal> FavoritePlaceForAnimals { get; set; }
//[S] favorite place is of type IPlaceForAnimals instead of PlaceForAnimals
public IPlaceForAnimals FavoritePlaceForAnimals { get; set; }
}
//[S]new interface
public interface IPlaceForAnimals
{
int CountAnimals();
}
//[S]abstract class implements the interface
public abstract class PlaceForAnimals<T>:IPlaceForAnimals where T : Animal
{
public List<T> Animals { get; set; }
public int CountAnimals()
{
//special counting using properties from Animal class
return 0;
}
}
A PlaceForAnimals<Dog> is not a PlaceForAnimals<Animal> (for purposes of assigning it that type), as it could not hold a tiger (while the original could).
The assignment is simply not legal without covariance. If you want to access certain methods you could have the base class implement a non-generic interface and make FavoritePlaceForAnimals be of that type.
The generic is wrapping a common set of functionality around a certain data type. Like List<int> functions the same as List<string>, it just gives you different data when you access it.
You could use a generic in the sense that your PlaceForAnimals<T> could have some defined behavior, but wrapped around a generic object like, say a Dog. But because it is just a wrapper around some functionality, it doesn't behave the same way as an inherited class like you have with your Animal superclass.
Inheritance lets you interchange data types, generics do not.

Best method to inherit common properties/methods into several models in Asp.NET MVC

Many tables in my database have common fields which I call 'audit' fields. They fields like - UserUpdateId, UserCreateId, DateUpdated, DateCreated, DateDeleted, RowGUID, as well as a common "Comments" table etc. In the database they are used to track who did what when. Additionally via the asp.net MVC 4 views they display these attributes to the user using common display templates (popup, mouseover etc.).
Currently, I put these properties into a [Serializable()] CommonAttributesBase class. Which I then initialize in all the models that should inherit those properties. Admittedly this is a little clunky and inefficient as my CommonAttribute class makes calls to the repository and the initialization seems like more code than necessary.
I would appreciate suggestions on how to implement this in the best way.
[Serializable()]
public class CommonAttributesBase
{
#region Notes
public Boolean AllowNotes { get; set; }
[UIHint("NoteIcon")]
public NoteCollection NoteCollection
{
get
{
if (!AllowNotes) return null;
INoteRepository noteRepository = new NoteRepository();
var notes = noteRepository.FindAssociatedNotes(RowGUID);
return new NoteCollection { ParentGuid = RowGUID, Notes = notes, AuditString = AuditTrail };
}
}
#region Audit Trail related
public void SetAuditProperties(Guid rowGuid, Guid insertUserGuid, Guid updateUserGuid, Guid? deleteUserGuid, DateTime updateDate, DateTime insertDate, DateTime? deleteDate)
{
RowGUID = rowGuid;
InsertUserGUID = insertUserGuid;
UpdateUserGUID = updateUserGuid;
DeleteUserGUID = deleteUserGuid;
UpdateDate = updateDate;
InsertDate = insertDate;
DeleteDate = deleteDate;
}
[UIHint("AuditTrail")]
public string AuditTrail
{
get
{
...code to produce readable user audit strings
return auditTrail;
}
}
...additional methods
}
In another class
public partial class SomeModel
{
private CommonAttributesBase _common;
public CommonAttributesBase Common
{
get
{
if (_common == null)
{
_common = new CommonAttributesBase { AllowNotes = true, AllowAttachments = true, RowGUID = RowGUID };
_common.SetAuditProperties(RowGUID, InsertUserGUID, UpdateUserGUID, DeleteUserGUID, UpdateDate, InsertDate, DeleteDate);
}
return _common;
}
set
{
_common = value;
}
}
...rest of model
}
For me, I prefer to use different interfaces for each type (audit or note), and use decorator to retrieve those related data, instead of embedding those in the common class:
public class Note
{
//Node properties
}
public class AuditTrail
{
//Audit trail properties
}
public interface IAuditable
{
AuditTrail AuditTrail { get; set; }
}
public interface IHaveNotes
{
IList<Note> Notes { get; set; }
}
public class SomeModel : IAuditable, IHaveNotes
{
public IList<Note> Notes { get; set; }
public AuditTrail AuditTrail { get; set; }
public SomeModel()
{
Notes = new List<Note>();
}
}
public class AuditRepository : IRepository<T> where T : IAuditable
{
private IRepository<T> _decorated;
public AuditRepository(IRepository<T> decorated)
{
_decorated = decorated;
}
public T Find(int id)
{
var model = _decorated.Find(id);
model.Audit = //Access database to get audit
return model;
}
//Other methods
}
public class NoteRepository : IRepository<T> where T : IHaveNotes
{
private IRepository<T> _decorated;
public NoteRepository(IRepository<T> decorated)
{
_decorated = decorated;
}
public T Find(int id)
{
var model = _decorated.Find(id);
model.Notes = //Access database to get notes
return model;
}
//Other methods
}
Advantages is that the client will be able to choose to load audit/note or not, the logic of audit and note are also separated from the main entity repository.
What you're doing is basically composition. As others have stated, there's many ways to accomplish what you're looking for, some better than others, but each method depends on the needs of your application, of which only you can speak to.
Composition
Composition involves objects having other objects. For example, if you were going to model a car, you might have something like:
public class Car
{
public Engine Engine { get; set; }
}
public class Engine
{
public int Horsepower { get; set; }
}
The benefit to this approach is that your Car ends up with a Horsepower property via Engine, but there's no inheritance chain. In other words, your Car class is free to inherit from another class while not effecting this property or similar properties. The problems with this approach is that you have to involve a separate object, which in normally is not too troubling, but when combined when tied back to a database, you're now talking about having a foreign key to another table, which you'll have to join in order to get all the class' properties.
Entity Framework allows you to somewhat mitigate this effect by using what it calls "complex types".
[ComplexType]
public class Engine
{
...
}
The properties of complex types are mapped onto the table for the main class, so no joins are involved. However, because of this, complex types have certain limitations. Namely, they cannot contain navigation properties -- only scalar properties. Also, you need to take care to instantiate the complex type or you can run into problems. For example, any nulled navigation property is not validated by the modelbinder, but if you have a property on your complex type that is required (which results in a property on your main class' table that is non-nullable), and you save your main class while the complex type property is null, you'll get an insertion error from the database. To be safe you should always do something like:
public class Car
{
public Car()
{
Engine = new Engine();
}
}
Or,
public class Car
{
private Engine engine;
public Engine Engine
{
get
{
if (engine == null)
{
engine = new Engine();
}
return engine;
}
set { engine = value; }
}
}
Inheritance
Inheritance involves deriving your class from a base class and thereby getting all the members of that base class. It's the most straight-forward approach, but also the most limiting. This is mostly because all of the .NET family of languages only allow single inheritance. For example:
public class Flyer
{
public int WingSpan { get; set; }
}
public class Walker
{
public int NumberOfLegs { get; set; }
}
public class Swimmer
{
public bool HasFlippers { get; set; }
}
public class Duck : ????
{
...
}
That's a bit contrived, but the point is that Duck is all of a Flyer, Walker and Swimmer, but it can only inherit from one of these. You have to be careful when using inheritance in languages that only allow single inheritance to make sure that what you inherit from is the most complete base class possible, because you won't be able to easily diverge from this.
Interfaces
Using interfaces is somewhat similar to inheritance, but with the added benefit that you can implement multiple interfaces. However, the downside is that the actual implementation is not inherited. In the previous example with the duck, you could do:
public class Duck : IFlyer, IWalker, ISwimmer
However, you would be responsible for implementing all the members of those interfaces on your Duck class manually, whereas with inheritance they just come through the base class.
A neat trick with interfaces and .NET's ability to extend things is that you can do interface extensions. These won't help you with things like properties, but you can move off the implementation of some of the class' methods. For example:
public static class IFlyerExtensions
{
public static string Fly(this IFlyer flyer)
{
return "I'm flying";
}
}
Then,
var duck = new Duck();
Console.WriteLine(duck.Fly());
Just by implementing IFlyer, Duck gets a Fly method, because IFlyer was extended with that method. Again, this doesn't solve every problem, but it does allow interfaces to be somewhat more flexible.
There's a couple different ways you could do something like this. I personally haven't worked with EF so I can't speak in regards to how it will work.
Option One: Interfaces
public interface IAuditable
{
Guid RowGUID { get; }
Guid InsertUserGUID { get; }
Guid UpdateUserGUID { get; }
Guid DeleteUserGUID { get; }
DateTime UpdateDate { get; }
DateTime InsertDate { get; }
DateTime DeleteDate { get; }
}
Of course you can change it to get and set if your use cases need that.
Option Two: Super/base classes
public abstract class AuditableBase
{
// Feel free to modify the access modifiers of the get/set and even the properties themselves to fit your use case.
public Guid RowGUID { get; set;}
public Guid InsertUserGUID { get; set;}
public Guid UpdateUserGUID { get; set;}
public Guid DeleteUserGUID { get; set;}
public DateTime UpdateDate { get; set;}
public DateTime InsertDate { get; set;}
public DateTime DeleteDate { get; set;}
// Don't forget a protected constructor if you need it!
}
public class SomeModel : AuditableBase { } // This has all of the properties and methods of the AuditableBase class.
The problem with this is that if you cannot inherit multiple base classes, but you can implement multiple interfaces.

Can you satisfy an interface with an IEnumerable<T> by using List<T>?

Let's say I have the following Model:
public interface IProduct
{
IEnumerable<Ingredient> Ingredients { get; set; }
}
public class Product : IProduct
{
public IEnumerable<Ingredient> Ingredients { get; set; }
}
public class Ingredient
{
}
But I want Ingredients to be a List<Ingredient> instead of an IEnumerable<Ingredient>
Is there a way to model the interface to accept IEnumerable<T> and List<T>?
I tried the following. But of course, the syntax doesn't support this and doesn't see TEnumerable<Ingredient> as a generic parameter.
public interface IProduct<TEnumerable<Ingredient>>
where TEnumerable<Ingredient> : IEnumerable<Ingredient>
{
TEnumerable<Ingredient> Ingredients { get; set; }
}
public class Product : IProduct
{
public List<Ingredient> Ingredients { get; set; }
}
public class Ingredient
{
}
I realize this isn't very practical, but I am just looking at this with curiosity in mind.
Your syntax is a bit off:
You can't declare a type parameter in a generic way like this
Your Product type needs to specify a type argument when it says how it's implementing IProduct<TEnumerable>
So this is valid:
public interface IProduct<TEnumerable>
where TEnumerable : IEnumerable<Ingredient>
{
TEnumerable Ingredients { get; set; }
}
public class Product : IProduct<List<Ingredient>>
{
public List<Ingredient> Ingredients { get; set; }
}
It may not be helpful, but at least it's valid...
Are you interested in having your concrete implementation of IProduct use List<> internally, or interested in exposing List<> in some implementations and IEnumerable in another?
If it's the former, you don't need to do anything - List<T> implements IEnumerable<T>, so if Product has an internal List<Ingredient>, you can simply return it as IEnumerable<Ingredient>:
public class Product : IProduct
{
private List<Ingredient> _ingredients;
public IEnumerable<Ingredient> Ingredients { get { return _ingredients; } }
}
If, however, you're interested in the second option (which Jon Skeet's answer fixes for you), I'll have to ask you why you'd want that, since it mainly makes the interface more difficult to consume - instead of having a uniform contract that all callers adhere to, you have an generic meta-interface that is used differently by different callers. It's an interesting concept, but seems like overkill if all you want to do is replace IEnumerable with IList.

How to create and set a polymorphic property?

I want to create a class that can take different types of value in a property. I am trying to do this using polymorphism, but I am not still learning how to do this properly, hence my request for advice.
I have a base class and two classes that inherit from it:
public abstract class BaseClass
{
public string Name { get; set; }
public Unit Unit { get; set; }
}
public class DerivedClassFloat : BaseClass
{
public float Value { get; set; }
public override string ToString()
{
return Value.ToString();
}
}
public class DerivedClassString : BaseClass
{
public string Value { get; set; }
public override string ToString()
{
return Value;
}
}
All is good, I can create a List and add different specialized subclasses. My problem comes when I need change the values of the items in my list:
foreach (var item in ListOfBaseClasses)
{
if(item is DerivedClassFloat)
((DerivedClassFloat) item).Value = float.NaN;
if (item is DerivedClassString)
((DerivedClassString) item).Value = string.Empty;
}
According to what I have read, that looks like a code smell. Is there a better way to access the value property of my derived classes based on the type I am trying to assign?
What about when you want to create the right subclass based on the value?
BaseClass newClass = null;
if (phenotype is DerivedClassFloat)
newClass = new DerivedClassFloat(){Value = 12.2};
if (phenotype is DerivedClassString)
newClass = new DerivedClassString(){Value = "Hello"};
I read about overriding virtual methods, but that works if I want to process the value, not to add or change it … maybe I am missing something?
I should make this more concrete, my apologies, I am not used to post question in this great site.
I need a property that is made of a list of attributes. Each attribute has a name and a value, but the value can be of different types. For example:
public class Organism
{
public string Name { get; set; }
public List<Attribute> Attributes { get; set; }
}
public class Attribute
{
public string AttributeName { get; set; }
public object AttributeValue { get; set; }
}
For a given organism I can have several attributes holding different value types. I wanted to avoid using the object type so that I don’t have to cast to the right type. I though property polymorphism was the solution to handle this case elegantly, but then I found myself using If ..Then which didn’t seem too different from casting in the first place.
If in your particular case you want to reset Value, you can define an abstract ResetValue method in the base class, which will be implemented by the derives classes.
As for your second case, you should check out Creational Design Patterns, and specifically the Factory and Prototype design patterns.
You can use generics to define the type and the implementing subclass will set the Value type to the type constraint:
public abstract class BaseClass<T>
{
public string Name { get; set; }
public Unit Unit { get; set; }
public T Value { get; set; }
public override string ToString()
{
return Value.ToString();
}
}
public class DerivedFloat : BaseClass<float> {}
public class DerivedString : BaseClass<string> {}
You can use Generics for this particular case:
public abstract class BaseClass<T>
{
public string Name { get; set; }
public Unit Unit { get; set; }
public T Value { get; set; }
}
public class DerivedClassFloat : BaseClass<float>
{
public override string ToString()
{
return Value.ToString();
}
}
public class DerivedClassString : BaseClass<string>
{
public override string ToString()
{
return Value;
}
}
Polymorphic behaviour works on abstraction. Based on what your trying to do, you can reduce code smell to moving as much of your variability in code to base classess.
i would suggest is instead of property write method like as follows. You can something like as follows.
public void setValue(string val, Type type);//move this to your base class
Class MyValue{
private string strVal;
private int intVal;
//constructor
MyValue(string val, Type type){
//check the type enum here and set the values accordingly
}
}
then when set values
foreach (var item in ListOfBaseClasses)
{
item.setValue = MyValue("",Type.INT);
}
I'm not quite sure what you are trying to achieve with this approach - the Value properties are not of the same type, there is also no Value property on the base class which suggests that other types derived from the base class might not have it at all.
If all of your classes require a Value property, then maybe it should be of the most general type object - you could put it onto the base class, but that would require casting the values in the derived classes.
But then you could have a NullObject to represent an absence of value that you could assign to the Value property for every derived class.
You can use the abstract factory pattern. Consider this example:
// Base class
class Button
{
protected Button()
{
}
public string Name { get; set; }
}
// Factory interface
public interface ButtonFactory
{
Button CreateButton();
}
// And the concrete classes
class WindowsButton : Button
{
// ...
}
class WindowsButtonFactory : ButtonFactory
{
public Button CreateButton()
{
return new WindowsButton();
}
}
class MacButton : Button
{
// ...
}
class MacButtonFactory : ButtonFactory
{
public Button CreateButton()
{
return new MacButton();
}
}
Furthermore, you can combine the abstract factory pattern with the strategy pattern to encapsulate the custom behaviors that change with type.

Help refactor my C# code to be more maintainable and to use best coding practices

I have this C# class structure that I would like to refactor to use best coding standards (use interfaces/abstract classes) so it can be more maintainable and reusable. The code as it is right now isn't awful, but it's not ideal.
I have a series of TableItemGroup classes: AccountTableItemGroup, PendingVoteTableItemGroup, and RequestingVoteTableItemGroup. Each TableItemGrup contains a string SectionName and a List for its corresponding TableItem ...as such:
public class AccountTableItemGroup {
public string SectionName { get; set; }
public List<AccountTableItem> Items
{
get { return this._items; }
set { this._items = value; }
}
public List<AccountTableItem> _items = new List<AccountTableItem>();
public AccountTableItemGroup()
{
}
}
In the future there will be many more TableItemGroups and if they are all the same except for the List part, I don't want to have to copy the code and create a new Group every time and make that small change. I know there must be a better way. I would like to keep using the List<> generics so I don't have to cast anything later though.
The other part are the TableItems. I have AccountTableItem, PendingVoteTableItem, and RequestingVoteTableItem. The TableItems are different from each other, but they each share three common strings -- TitleLabel, DetailLabel, and ImageName. But after that, each TableItem may or may not have additional properties or methods along with it ..as such:
public class AccountTableItem
{
public string TitleLabel { get; set; }
public string DetailLabel { get; set; }
public string ImageName { get; set; }
public bool SwitchSetting { get; set; }
public AccountTableItem()
{
}
}
So my question to all of you is, how do I redefine my class structure to allow for as much reuse of code as possible and to use best coding standards?
I was thinking of having an abstract TableItem class or use an interface for the TableItemGroup? I know that using an interface or an abstract class is best for coding standards, but I don't see how it would cut down on the amount of code I will have?
Thanks a lot for any help.
Abstract away your table item adding necessary fields to the interface or base class:
interface ITableItem // or just a simple or abstract class
{
// common fields go here
}
Then can you make your item group generic with a constraint on generic parameter.
public class ItemGroup<T> where T: ITableItem
{
public string SectionName { get; set; }
public List<T> Items { get; private set; }
public ItemGroup()
{
Items = new List<T>();
}
}
Consider using generics to represent the TableItemGroup container, and make a base class for your TableItem, which you can inherit from for specific types of table item. If you inherit directly from List<T>, then you can treat your item group as a collection without having to use the Items property as in your existing design.
There's not much point in using interfaces for these sorts of types. As they stand they are data classes so have no behavior. If they had behavior, using interfaces would make sense as you would then be able to change implementations and so vary behavior.
public class TableItemGroup<T> : List<T> where T : TableItem
{
public TableItemGroup(string sectionName)
{
SectionName = sectionName;
}
public string SectionName { get; private set; }
}
public class TableItem
{
public string TitleLabel { get; set; }
public string DetailLabel { get; set; }
public string ImageName { get; set; }
}
public class AccountTableItem : TableItem
{
public bool SwitchSetting { get; set; }
}
Now that we have a generic TableItemGroup container, you can re-use this for all TableItem types. Having a base class for TableItem again gives you some re-use.
var items = new TableItemGroup<AccountTableItem>("Accounts");
items.Add(new AccountTableItem { SwitchSetting = true });
Unless you want users to be able to add and remove new lists at will, you should make the setter on the items list protected. Users will still be able to add and remove items, but not create a reference to a new list.

Categories

Resources