No derived ViewModels but the same behavior? - c#

I'm writing a small wpf desktop application. My BaseViewModel looks like this:
public abstract class BaseViewModel : INotifyPropertyChanged, IComparable<BaseViewModel>
{
public abstract string GetDisplayText();
public abstract string GetImageName();
// INotifyPropertyChanged
}
I was looking for a best paxis for mvvm. The most say, that there are multiple ViewModels for one Model and I agree to it.
Because I want that all ViewModels of the same type handle the basics in the same way, i thougth they should derived from each other.
public abstract class BaseCustomerVm : BaseViewModel
{
public abstract string Name { get; set; }
public abstract int Number { get; set; }
public abstract bool IsPerson { get; set; }
public override string GetDisplayText()
{
return Name;
}
public override string GetImageName()
{
if (IsPerson)
return "Person";
else
return "Company";
}
}
public class Customer1Vm : BaseCustomerVm
{
public override string Name { get; set; }
public override int Number { get; set; }
public override bool IsPerson { get; set; }
}
To implement this, I have the following options:
Version 1:
public class Customer2Vm : BaseCustomerVm
{
public override string Name { get; set; }
public override int Number { get; set; }
public override bool IsPerson { get; set; }
// Further Properties
}
Version 2:
public class Customer2Vm : Customer1Vm
{
// Further Properties
}
In my search, I read ViewModels shouldn't derive from each other. This was also answerd in this post. My questions are:
Why should I not derive in this way?
What would be the correct way to handle sutch basics with no inheritance?

Inheritance shouldn't be an issue until you reach the point where you need to inherit from more than one (base) view model, i.e. if you have several different base view models that provide their own common base functionality.
Since you can't inherit from more than one class in C#, you then need to break out the common functionality into reusable components that you can inject into your view models.
But the only way you will be able to directly bind to some common properties that are defined in a class is to use inheritance and there is nothing wrong with inheriting from a chain of different base view model classes. In fact, this is a pretty common approach in my experience. Most of the types used in the view (Control, FrameworkElement, etc.) also do this.

As far as if Customer2Vm should derive from Customer1Vm; I think you want the classic inheritance question:
Does Customer2Vm have a "is-a" relationship with Customer1Vm?
Only you know; but based on the names I would doubt it. Sounds to me like they should both be deriving from BaseCustomerVm.
As far as whether or not you should be using inheritance at all; I would say that it largely seems OK here. If you wanted to avoid it (and strictly prefer composition) I would suggest making your VMs implement an ICustomerVm interface to get the properties; and then the consumer would use services to get the display text and image name. I would probably stick with what you have (assuming its more or less exactly what you've shown).

Related

How to derive from/implement a C# class hierarchy in without code duplication

I am faced with a C# design problem that C#'s limitations are making hard to achieve. I need some sort of design pattern/strategy to rescue me.
I must create the archetypical set of abstract shape classes: Base class Shape with derived classes LineShape, RectShape, etc. Specific implementations will derive from these. The problem is that I really need to use classes here, not interfaces and this is forcing me to duplicate a lot of code.
To illustrate:
public abstract class Shape
{
public abstract int Id { get; } // Unique ID
public abstract string Name { get; set; } // Shape name. Defaults to the type of shape
public abstract bool IsLocked { get; set; } // May the user change this shape in any way?
}
public abstract class LineShape : Shape
{
public abstract Point P1 { get; set; }
public abstract Point P2 { get; set; }
}
public abstract class CircleShape : Shape
{
public abstract Point Center { get; set; }
public abstract double Radius { get; set; }
}
When I start creating the derived implementations (LineImpl, CircleImpl, etc), I find that the implementations of the Shape functions are identical for all the Impl classes, yet specific enough that I cannot implement them in the abstract Shape class itself.
So I need to find a way to share a common implementation of these function in my derived hierarchy.
In other words LineImpl must derive from LineShape. CircleImpl must derive from CircleShape, etc. I cannot find a way to insert a ShapeImpl in there to handle the boiler plate stuff. So I am forced to implement all those Shape functions over and over again, once in each Impl shape type.
I tried using generics to get my way out of this but unfortunately a generic class cannot specify its base class with a generic argument. In other words, the following approach (which I might do in C++) does not work in C#
public class ShapeImpl<TBase> : T where T : Shape { ... boiler plate implemented here)...}
public class LineImpl : ShapeImpl<LineShape> { }
public class CircleImpl : ShapeImpl<CircleShape> { }
So I am at a loss. Is there some C# trick or design pattern that can get me out of this? Or am I forced to implement the same functions multiple times?
yet specific enough that I cannot implement them in the abstract Shape class itself.
You also mentioned:
I find that the implementations of the Shape functions are identical for all the Impl classes
I think that this is classic case of over-thinking for future implementation. if you say- the implementation is identical for all classes, I wouldn't bother too much over thinking for something in the future that may never arrive.
But, if you insist, you may implement it in the following way:
public abstract class Shape
{
public abstract int Id { get; } // Unique ID
public abstract string Name { get; set; } // Shape name. Defaults to the type of shape
public abstract bool IsLocked { get; set; } // May the user change this shape in any way?
public abstract void Foo();
}
public abstract class SepcificShape : Shape
{
protected virtual void FooSpecific()
{
Console.WriteLine("Specific Implementation");
}
}
public abstract class LineShape : SepcificShape
{
public abstract Point P1 { get; set; }
public abstract Point P2 { get; set; }
}
public class LineImp : SepcificShape
{
public override int Id { get; }
public override string Name { get; set; }
public override bool IsLocked { get; set; }
public override void Foo()
{
base.FooSpecific();
}
}
The only way to achieve something similar to multiple inheritance in C# I can think of would be to use default interface implementations, e.g. like this:
interface IShapeSdk
{
string GetNameSdk() => "Shape SDK name";
}
abstract class Shape
{
public abstract string GetName();
}
class ShapeImpl : Shape, IShapeSdk
{
public override string GetName()
{
return ((IShapeSdk)this).GetNameSdk();
}
}
This way all shapes will inherit from Shape, but only the external-SDK-shapes will inherit the common logic defined in IShapeSdk.
Not the cleanest approach, and a lot of C# developers are against the usage of this relatively new feature (which by the way is available only in C# 8 and above and .NET Core 3.0 and above).

Trying to understand C# nested interfaces

I'm trying to get a simple set of interfaces to be nested so I can enforce some members on derived classes.
public enum Category { Mental, Physical, Technical }
interface IAbilities
{
List<IAbility> Abilities { get; set; }
}
interface IAbility
{
Category Category { get; }
int Value { get; set; }
string Descritpion { get; set; }
}
public class MentalAbilities : IAbilities
{
// This is what I want so that "Abilities" is accessible
public List<MentalAbility> Abilities { get; set; }
// This is what Intellisense generates, cannot be set to public
//List<IAbility> IAbilities.Abilities { get; set; }
}
public class MentalAbility : IAbility
{
public Category Category { get; } category
public int Value { get; set; }
public string Descritpion { get; set; }
}
Of course the Intellisense generated bit compiles, but "Abilities" is not accessible from a class instance because it can't be set to public.
The bit I want tells me `'MentalAbilities' does not implement interface member 'IAbilities.Abilities'. 'MentalAbilities.Abilities' cannot implement 'IAbilities.Abilities' because it does not have the matching return type of List<IAbility>.
I don't understand since "MentalAbility" is derived from the "IAbility" interface so that should fulfill the contract.
(I'm skipping over the "x is less accessible than y" error because you already worked out you can make your interfaces public - sure you can appreciate how anything has to be at least as accessible as it's use)
Re your "does not implement" error:
I understand your problem, but you've kinda got it upside down
I see that you want to ensure, in your MentalAbilities.Abilities list, someone only puts MentalAbility objects.. and they implement IAbility so it should satisfy the "object is a IAbilities and has a list which contains only things that implement IAbility" rules, right?
Alas, no. This the pretty much the opposite of what inheritance or interface implementation is for.
The idea behind inheritance is that you can say "this thing can be any type at all as long as it has these common aspects and I will treat it in the common way". By declaring such that List<IAbility> you're saying "objects in this list just have to implement IAbility and then I'll be able to deal with them" - it could be a MentalAbility, or a PhysicalAbility - doesn't matter
You cannot then constrain the list to only containing MentalAbility via the inheritance/implements mechanism, nor should you because it's opposite of what it is for- going from "I can deal with anything so long as it implements X" to "I will only deal with something if it is, or is a subtype of, Y" is the opposite of what was claimed earlier. You're saying that MentalAbilities can only deal with the list contents if they're MentalAbility, when you earlier said it could deal with anything that was an IAbility
If you want to enforce that MentalAbilities only contains MentalAbility you'll have to declare it as List<IAbility> and look at the type of the IAbility you're given in the set and refuse to add it if if it's not a MentalAbility, but if other developers use your code they will be very confused - "what? It says I'm allowed to use anything that implements IAbility, and my TigerAbility does just that.. why am I getting an exception that it must be a MentalAbility? Why did this developer even use a List(IAbility) if I'm not allowed to sling any IAbility I like into it?" - it's also no longer a compile time thing, but a runtime one and that's a big risk
I think you need to decide if you're going to be able to treat these things in a generic way i.e. can your AbilitiesProcessor implement IAbilities and have a list of IAbility and process them regardless of actual type, or not. If it can't, and you're going to have a MentalAbilities class that can only deal with MentalAbility that's fine, and it can have a List<MentalAbility> all it wants, fellow developers won't mistakenly put a TigerAbility into it, but it won't implement the IAbilities interface
I'm trying to get a simple set of interfaces to be nested so I can enforce some members on derived classes.
Your main issue here is that defined the two interfaces as private by default. That's what is preventing you from creating public List<IAbility> Abilities { get; set; } inside MentalAbilities.
Actually, the property public List<MentalAbility> Abilities { get; set; } is also preventing you as you can't have a property of the same name defined twice.
The big question here would be what would be the point of allowing MentalAbilities the ability to set a List<IAbility> since that would mean setting any type of ability.
Ideally MentalAbilities should only have a single list of MentalAbility that it contains - and it should only be read-only. In fact, most of your interfaces should be read-only.
Here's what you should do:
Start with these interfaces:
public interface IAbilities<A> where A : IAbility
{
List<A> Abilities { get; }
}
public interface IAbility
{
Category Category { get; }
int Value { get; }
string Description { get; }
}
Notice the IAbilities<A> interface uses a generic type A that you can fill in later.
Next, let's set up some base classes that simplify the implementation of each specific class.
public abstract class AbilitiesBase<A> : IAbilities<A> where A : IAbility
{
public List<A> Abilities { get; protected set; }
}
public abstract class AbilityBase : IAbility
{
public abstract Category Category { get; }
public abstract int Value { get; }
public abstract string Description { get; }
}
Now the final classes are simple:
public class MentalAbilities : AbilitiesBase<MentalAbility> { }
public class MentalAbility : AbilityBase
{
public override Category Category => Category.Mental;
public override int Value => 42;
public override string Description => "Mental!";
}
There's nothing to implement in MentalAbilities - the base class took care of that - but it does have a List<MentalAbility> Abilities { get; } property.
MentalAbility is also neatly set up to enforce you to override the properties.
Now, if you actually wanted still have a List<IAbility> Abilities { get; } property then there's an easy way to do that by writing these two interfaces:
public interface IAbilities
{
List<IAbility> Abilities { get; }
}
public interface IAbilities<A> : IAbilities where A : IAbility
{
new List<A> Abilities { get; }
}
This forces a change to AbilitiesBase like this:
public abstract class AbilitiesBase<A> : IAbilities<A> where A : IAbility
{
public List<A> Abilities { get; protected set; }
List<IAbility> IAbilities.Abilities => this.Abilities.Cast<IAbility>().ToList();
}
The List<IAbility> IAbilities.Abilities property generates a copy of the public List<A> Abilities { get; protected set; } property, but that's what you want to prevent anyone adding the wrong type of ability to the original list.
Personally, I would go with this instead:
public interface IAbilities
{
IEnumerable<IAbility> Abilities { get; }
}
public interface IAbilities<A> : IAbilities where A : IAbility
{
new List<A> Abilities { get; }
}
public abstract class AbilitiesBase<A> : IAbilities<A> where A : IAbility
{
public List<A> Abilities { get; protected set; }
IEnumerable<IAbility> IAbilities.Abilities => this.Abilities.Cast<IAbility>();
}
What you are stuck with is called implicit and explicit implementation of interfaces in C#. If you define your class member like this:
public List<MentalAbility> Abilities { get; set; }
you are implementing IAbilities implicitly and you need to write public with it. If you define your class member as
List<IAbility> IAbilities.Abilities { get; set; }
you have implemented IAbilities explicitly, in which case it can be private.
While we are here, I see no point in defining an interface IAbilities. You should simply use IEnumerable<IAbility> anywhere you want to use IAbilities, which is literally providing no value in your code.

Not sure which solution to choose (property used across two domain models, shared validation)

I've got 2 classes with many different properties and one similar property:
public class A
{
// Lots of specific properties
[Display(Name="Dun and bradstreet number")]
public string DunAndBradstreetNumber {get;set;}
}
public class B
{
// Lots of specific properties
[Display(Name="Dun and bradstreet number")]
public string DunAndBradstreetNumber {get;set;}
}
I realise I have an abundance of choice and I just want to make sure i'm choosing the most semantically correct and popular choice.
1:-----------
Should I declare another class:
public class DunAndBradstreetNumber
{
[Display(Name="Dun and bradstreet number")]
public string DunAndBradstreetNumber {get;set;}
}
and then make class A and B have pointers inside them eg.?
public class A
{
public DunAndBradstreetNumber DunAndBradstreetNumber { get; set; }
}
or
2:-----------
inherit from the DunAndBradstreetNumber?
public class A : DunAndBradstreetNumber
{
//...
}
3:-----------
declare a global function and put that in the get method of each DunAndBradstreetNumber?
public class A
{
public string DunAndBradstreetNumber {
get
{
// Run some function that I may need help on to apply property validation via attributes to
}
set;
}
}
Any more better choices?
My class A and B are domain models using entityframework if that helps at all.
The problem i'm trying to solve is to not have to declare the validation and display attributes twice in different models.
P.S - your opinion is fine... I just want to know the eventualities of the choice I have to make here (albeit its relative insignificance).

Implementing interfaces within interfaces

I'm writing some code for importing files which will import either delimited or fixed width files based on a template that describes the file layout.
I've created an interface IFileTemplate:
public interface IFileTemplate
{
string Name { get; set; }
bool IgnoreEmptyLines { get; set; }
}
which is used by a DelimitedFileTemplate class and a FixedWidthFileTemplate class.
I also have an interface for specifying each of the columns that make up a template:
public interface IFileTemplateColumn
{
int ID { get; set; }
string Name { get; set; }
bool Ignore { get; set; }
}
This interface is then used by a DelimitedTemplateColumn class and a FixedWidthTemplateColumn class.
As both the DelimitedFileTemplate and FixedWidthFileTemplate classes will have a list of columns I've made the list a member of the IFileTemplate column:
List<IFileTemplateColumn> Fields { get; set; }
My problem is when I've come to implement the list in the DelimitedFileTemplate and FixedWidthFileTemplate classes, for example:
public class FixedWidthFileTemplate : IFileTemplate
{
public int ID { get; set; }
public string Name { get; set; }
public List<FixedWidthFileTemplateColumn> Fields { get; set; }
}
If I try and implement List<IFileTemplateColumn> with List<DelimitedFileTemplateColumn> or List<FixedWidthFileTemplateColumn> then the compiler complains that they don't match List<IFileTemplateColumn>.
I can understand this but it seems wrong not to have the column list in the ITemplateInterface. The only get around I can think of is to have the Delimited and FixedWidth classes use List<IFileTemplateColumn> and have the property getter cast the list to the delimited or fixed width column list but there seems a bit of code smell to that. Can anyone suggest a better way for doing this?
A suitable and not smelly solution to this design problem are generics:
interface IFileTemplate<T> where T : IFileTemplateColumn
{
List<T> Fields { get; set; }
}
DelimitedFileTemplate implements IFileTemplate<DelimitedFileTemplateColumn> and so on.
Perhaps all the differences between the file templates could be sensibly defined by IFileTemplateColumn only and you could simplify things with FileTemplate<IFileTemplateColumn> insted of one FileTemplate class per one FileTemplateColumn class relation.
Update
As for the factory method: IFileTemplate<IFileTemplateColumn> Create: if the consumers of this method are supposed to be able to access the list of columns, the method signature will have to contain the concrete ColumnTemplate. For example:
DelimitedFileTemplate Create
or
interface IFactory<T> where T : IFileTemplateColumn
{
IFileTemplate<T> Create();
}
class DelimitedFactory : IFactory<DelimitedFileTemplateColumn>
{
IFileTemplate<DelimitedFileTemplateColumn> Create()
{
return new DelimitedFileTemplate();
}
}
If the consumers of the method won't be interested in the list, introduce a more general interface (much like IEnumerable<T> : IEnumerable):
interface IFileTemplate { ... }
interface IFileTemplate<T> : IFileTemplate where T : IFileTemplateColumn
{
List<IFileTemplateColumn> Columns { get; set; }
}
Then your IFileTemplate Create() method could return any of the concrete FileTemplate regardless of the column.
I've worked with this kind of generics usage and they might tend to propagate (in this example Column hierarchy will be duplicated in FileTemplate hierarchy and might be duplicated in the factory hierarchy). Sometimes this reveals some flaws in the design. If you were able to sensibly cut the IFileTemplate hierarchy to one base parametrized FileTemplate class, this was certainly the way to go. This is how I often use this: define the smallest parts, if the hierarchy tends to duplicate, some parts of the algorithms can be perhaps moved to the 'smallest-parts-classes'.

Downcast on POCO classes

I have a group of POCO classes:
class ReportBase
{
public string Name { get; set; }
public int CustomerID { get; set; }
}
class PurchaseReport : ReportBase
{
public int NumberOfPurchases { get; set; }
public double TotalPurchases { get; set; }
public bool IsVip { get; set; }
}
class SaleReport : ReportBase
{
public int NumberOfSales { get; set; }
public double TotalSales { get; set; }
}
I have a web method to return ReportBase. The caller uses the return value to update UI(WPF) based on the actually type by downcasting and checking the type (one grid for sale and one for purchase). Someone suggested to use three web methods and each return the specific type.
I understand that downcast is in general against design principle by introducing if/else. Instead we should use virtual functions. But in POCO class, we don't really have virtual behaviors (only extra fields).
Are you for or against downcast in this case, why?
IMO it's all about intention. Returning just the base class doesn't say anything, especially as you return it only to save some key strokes. As a developer what do you prefer?
ReportBase GetReport() // if type==x downcast.
//or
PurchaseReport GetPurchaseReport()
SaleReport GetSalesReport()
What approach would you want to use to make the code more maintainable? Checking type and downcasting is an implementation detail after all and you probably have a method like this
public void AssignReport(ReportBase report)
{
//check, cast and dispatch to the suitable UI
}
What's wrong with this? It's lacking transparency, and this method should always know about what reports are needed by what UI elements. Any time you add/remove an element you have to modify this method too.
I think is much clear and maintainable something like this
salesGrid.DataSource=repository.GetSalesReport();
purchaseGrid.DataSource=repository.GetPurchaseReport();
than this
var report=repository.GetReport();
AssignReport(report); //all UI elements have their data assigned here or only 2 grids?
So I think that, POCO or not, I will favour the three web methods approach.

Categories