Say I have a class Book:
public class Book{
public string Title {get; set;}
}
I want every book to have a Read function that returns a string and accepts a page number - but the internals will be different for every book (poor example, I know). How do I define the signature of a function that must be implemented by instances of this class?
Something like this:
public class Book{ // need to make this abstract?
public string Title {get; set;}
public abstract string Read(int pageNum);
}
// I want to define instances that define their own behavior...
public static Book It => new Book(){ // can't create instance of abstract...
Title = "It",
Read... // what do I do here?
}
My main concerns are:
Keeping things as simple as possible. Implementing interfaces under abstract classes works, but it gives me n*2 things to worry about as I add more instances.
I will need to add a large number of these custom functions - passing Funcs through constructors seems unwieldy.
In practice - this is used to define a Tenant. The Tenants are defined in-memory, and have many static properties like domain, name, adminEmail, etc. Those are tenant-specific properties... but now I am trying to implement tenant-specific behaviors - like GetBooks or FilterUsers. I would like to keep implementation as simple as humanly possible. Right now I have "If TenantA, do this, else if tenantB, do this..." sprinkled throughout my code. I'm trying to consolidate all tenant-specific logic and detail in one place - on instances of the Tenant class.
Further examples of Tenant specific behavior - you have a SaaS forum software. On the homepage of Forum A, you GetCoverPhoto by reading from a static file. On the homepage of Forum B, you GetCoverPhoto by reading from a blog homepage. Currently, I say "If Forum A, do this, else If Forum B, do this". This is the type of tenant-specific behavior that I want to define on the Tenant object, instead of in code. I don't want any tenant-specific code in my core logic.
Is there a simple feature/pattern in the C# language that will achieve this?
What NineBerry said is very valid.
There is one other way of accomplishing what you might want. If you want to dynamicly inject the read method implementation into a Book. This can be seen as strategy pattern. And can be done as interfaces like in many languages, but in simplest form in C# it can be done by delegates. Example:
public class Book{
Func<int, string> readFunc;
public Book(Func<int, string> readFunc)
{
this.readFunc = readFunc;
}
public string Title {get; set;}
public string Read(int pageNum) { return readFunc(pageNum); }
}
Then use it as:
public static Book It => new Book(){
Title = "It",
Read = (pageNum) => ... // Do actual reading in delegate
}
EDIT: With more detail on requirements (but still not everything is obvious) I would do something like this:
public class Tenant
{
// core things go here
public Extensions Extensions { get; }
}
public class Extensions : IEnumerable<IExtension>
{
private IList<IExtension> list = new List<IExtension();
private Tenant { get; set; }
public Extensions(Tenant tenant)
{
Tenant = tenant;
}
public void Add(IExtension extension)
{
extension.Tenant = Tenant;
list.Add(extension);
}
}
public interface IExtension
{
Tenant { get; set; }
// shared interface of extensions if any can be abstracted
}
public interface ICoverPhotoExtension : IExtension
{
Photo GetCoverPhoto();
}
public class FileCoverPhotoExtension : ICoverPhotoExtension
{
public Tenant { get; set; }
Photo GetCoverPhoto() { } // gets photo from file
}
public class BlogCoverPhotoExtension : ICoverPhotoExtension
{
public Tenant { get; set; }
Photo GetCoverPhoto() { } // gets photo from blog
}
usage:
Tenant tenant; // initialized somehow
var coverPhotoExtension = tenant.Extensions.FirstOrDefault<ICoverPhotoExtension>();
Photo photo = coverPhotoExtension?.GetCoverPhoto();
public Interface IBook{
string Title {get; set;}
func<int,string> ReadPage
}
Use containment over inheritance. In the interface example above there is a function in every book that implements IBook that will return a string for that page.
public class MyBook : IBook{
public Title : {get;set;} = "MyBook";
public func<int,string> ReadPage =(pagenumber)=>{
return GetText(pagenumber);
}
public string GetText(int pageNumber){
//read the page text by number here.
}
}
I would make GetText an extension method similar to this, so each book doesn't need to implement GetText itself.
public static class XBook{
public static string GetText(this IBook book, int pageNumber){
///do the work here and returng string
}
}
To use the Extension method concept:
using XBook;
public class MyBook : IBook{
public Title : {get;set;} = "MyBook";
public func<int,string> ReadPage =(pagenumber)=>{
return this.GetText(pagenumber);
}
}
There are more ways to do this... for now, give it a try.
Having different instances of a class implement functions differently is not possible. Instead, you inherit a new class where you implement the separate behaviour.
public abstract class Book
{
public string Title {get; set;}
public abstract string Read(int pageNum);
}
public class ITBook : Book
{
public override string Read(int pageNum)
{
// Code here
}
}
Then use the class like this:
public static Book It => new ITBook()
{
Title = "It",
}
You could use a property of a delegate type in the Book class to use different functions in different instances of the Book class, but these functions would not have access to the other properties and methods of the instance they would be used by.
This is kind of a design problem:
class Suite
{
List<Plugins> Plugins {get;set;}
}
class DataCollector : Plugin
{
string Property1 {get;set;}
string Property2 {get;set;}
public void PrintMyName();
}
class Measurement: Plugin
{
string Property1 {get;set;}
string Property2 {get;set;}
public void PrintMyName();
}
Now, I want the class suite to be serializable. The problem here is this:
XMl serialization is basically used to serialize DTO kind of objects so you basically serialize/deserialize your stateful properties and that is fine
This particular class which is going to serialized contains of Type Plugin(which contains combination of properties which contains some property values) + functionalists.
Which means I need to use factory to get the real instance of the object for Plugin to come to life with all its functionality with the property values.
Am I looking at an XMLSrializable + Factory combination? Is there any good elegant way to achieve this?
Why not implement the IDeserializationCallback interface so upon deserialization you can bring your object back to life via a call to your factory.
I don't really understand the purpose of your classes, but I will give an example as best I can:
public class MyDataClass : IDeserializationCallback
{
public int SimpleKeyProperty { get; set; }
public string TextProperty{ get; set; }
public void OnDeserialization(object sender)
{
//upon deserialization use the int key to get the latest value from
//factory (this is make believe...)
TextProperty = SomeFactory.GetCurrentValue( this.SimpleKeyProperty) ;
}
}
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).
I have several different entities in my domain model (animal species, let's say), which have a few properties each. The entities are readonly (they do not change state during the application lifetime) and they have identical behavior (the differ only by the values of properties).
How to implement such entities in code?
Unsuccessful attempts:
Enums
I tried an enum like this:
enum Animals {
Frog,
Duck,
Otter,
Fish
}
And other pieces of code would switch on the enum. However, this leads to ugly switching code, scattering the logic around and problems with comboboxes. There's no pretty way to list all possible Animals. Serialization works great though.
Subclasses
I also thought about where each animal type is a subclass of a common base abstract class. The implementation of Swim() is the same for all Animals, though, so it makes little sense and serializability is a big issue now. Since we represent an animal type (species, if you will), there should be one instance of the subclass per application, which is hard and weird to maintain when we use serialization.
public abstract class AnimalBase {
string Name { get; set; } // user-readable
double Weight { get; set; }
Habitat Habitat { get; set; }
public void Swim(); { /* swim implementation; the same for all animals but depends uses the value of Weight */ }
}
public class Otter: AnimalBase{
public Otter() {
Name = "Otter";
Weight = 10;
Habitat = "North America";
}
}
// ... and so on
Just plain awful.
Static fields
This blog post gave me and idea for a solution where each option is a statically defined field inside the type, like this:
public class Animal {
public static readonly Animal Otter =
new Animal
{ Name="Otter", Weight = 10, Habitat = "North America"}
// the rest of the animals...
public string Name { get; set; } // user-readable
public double Weight { get; set; }
public Habitat Habitat { get; set; }
public void Swim();
}
That would be great: you can use it like enums (AnimalType = Animal.Otter), you can easily add a static list of all defined animals, you have a sensible place where to implement Swim(). Immutability can be achieved by making property setters protected. There is a major problem, though: it breaks serializability. A serialized Animal would have to save all its properties and upon deserialization it would create a new instance of Animal, which is something I'd like to avoid.
Is there an easy way to make the third attempt work? Any more suggestions for implementing such a model?
If you have issues with serialization, you can always separate the application-code from the serialization code. That is, place conversion classes that convert to/from your serialized state. The serialized instances can have exposed any empty constructors and properties needed and their only job is to serialize state. Meanwhile, your application logic works with the non-serializable, immutable objects. This way you do not mix your serialization concerns with logical concerns which brings with it a host of disadvantages as you are finding out.
EDIT: Here's some example code:
public class Animal
{
public string Name { get; private set; }
public double Weight { get; private set; }
public Habitat Habitat { get; private set; }
internal Animal(string name, double weight, Habitat habitat)
{
this.Name = name;
this.Weight = weight;
this.Habitat = habitat;
}
public void Swim();
}
public class SerializableAnimal
{
public string Name { get; set; }
public double Weight { get; set; }
public SerializableHabitat Habitat { get; set; } //assuming the "Habitat" class is also immutable
}
public static class AnimalSerializer
{
public static SerializableAnimal CreateSerializable(Animal animal)
{
return new SerializableAnimal {Name=animal.Name, Weight=animal.Weight, Habitat=HabitatSerializer.CreateSerializable(animal.Habitat)};
}
public static Animal CreateFromSerialized(SerializableAnimal serialized)
{
return new Animal(serialized.Name, serialized.Weight, HabitatSerializer.CreateFromSerialized(serialized.Habitat));
}
//or if you're using your "Static fields" design, you can switch/case on the name
public static Animal CreateFromSerialized(SerializableAnimal serialized)
{
switch (serialized.Name)
{
case "Otter" :
return Animal.Otter
}
return null; //or throw exception
}
}
Then your application logic for serialization might look something like:
Animal myAnimal = new Animal("Otter", 10, "North America");
Animal myOtherAnimal = Animal.Duck; //static fields example
SerializableAnimal serializable = AnimalSerializer.CreateSerializable(myAnimal);
string xml = XmlSerialize(serializable);
SerializableAnimal deserialized = XmlDeserializer<SerializableAnimal>(xml);
Animal myAnimal = AnimalSerializer.CreateFromSerialized(deserialized);
Just to reiterate, the SerializableAnimal class and usage is ONLY used in the final layer(s) of your application that need to serialize/deserialize. Everything else works against your immutable Animal classes.
EDITx2: Another major benefit of this managed separation is you can deal with legacy changes in your code. For example, you have a Fish type, which is pretty broad. Maybe you split it into Shark and Goldfish later and decide all your old Fish type should be considered Goldfish. With this separation of serialization, you can now place a check for any old Fish and convert them to Goldfish whereas direct serialization would result in an exception because Fish no longer exists.
I would implement it with subclasses, but where the instances of the subclasses don't store any data, like this:
public abstract class AnimalBase {
public abstract string Name { get; } // user-readable
public abstract double Weight { get; }
public abstract Habitat Habitat { get; }
public void Swim(); { /* swim implementation; the same for all animals but uses the value of Weight */ }
// ensure that two instances of the same type are equal
public override bool Equals(object o)
{
return o != null && o.GetType() == this.GetType();
}
public override int GetHashCode()
{
return this.GetType().GetHashCode();
}
}
// subclasses store no data; they differ only in what their properties return
public class Otter : AnimalBase
{
public override string Name { return "Otter"; }
public override double Weight { return 10; }
// here we use a private static member to hold an instance of a class
// that we only want to create once
private static readonly Habitat habitat = new Habitat("North America");
public override Habitat Habitat { return habitat; }
}
Now it shouldn't matter that you have multiple "instances", because each instance only contains its type information (no actual data). Overriding Equals and GetHashCode on the base class means that different instances of the same class will be considered equal.
The way I see it, you are looking for the right creational pattern to suit your needs.
Your first option is similar to factory method.
The second one looks like a type hierarchy with an optional abstract factory.
The third one is a singleton.
It seems like your only problem is serialization. What kind of serialization we're talking about: binary or XML? If it's binary, have you looked at custom serialization? If it's XML, you should either stick with the second option, also use custom serialization or delegate the serialization logic outside of your classes.
I personally think the latter is the most architecturally sound solution. Mixing object creation and serialization is a bad idea.
I'd go with the third option (objects!), but with a little twist.
The point is: You have a set of objects with some particular schema...
public class Animal {
public string Name { get; set; } // user-readable
public double Weight { get; set; }
public Habitat Habitat { get; set; }
public void Swim();
}
but you want them to be predefined. The catch is: If you serialize such object, you don't want to have its fields serialized. Initializing the fields is the responsibility of application, and the only thing you want to actually have in your serialized version is the "type" of the animal. This will allow you to change "Otter" to "Sea Otter" and keep the data consistent.
Hence, you'd need some representation of the "animal type" - and that's the only thing you want to have serialized. On deserialization, you want to read the type identifier and initialize all the fields based on it.
Oh, and another catch - upon deserialization, you don't want to create a new object! You want to read the ID (and the ID only) and retrieve one of the predefined objects (that corresponds to this ID).
The code could look like:
public class Animal {
public static Animal Otter;
public static Animal Narwhal;
// returns one of the static objects
public static Animal GetAnimalById(int id) {...}
// this is here only for serialization,
// also it's the only thing that needs to be serialized
public int ID { get; set; }
public string Name { get; set; }
public double Weight { get; set; }
public Habitat Habitat { get; set; }
public void Swim();
}
So far, so good. If there are dependencies that prohibit you from making instances static, you could throw in some lazy initialization for all the Animal objects.
The Animal class starts to kind of look like "a couple singletons in one place".
Now how to hook it into .NET's serialization mechanism (BinarySerializer or DataContractSerializer). We want the serializer to use GetAnimalById instead of the constructor when deserializing, and only store ID when serializing.
Depending on your serialization API, you can do this with ISerializationSurrogate or IDataContractSurrogate. This is an example:
class Surrogate : IDataContractSurrogate {
public Type GetDataContractType(Type type) {
if (typeof(Animal).IsAssignableFrom(type)) return typeof(int);
return type;
}
public object GetObjectToSerialize(object obj, Type targetType) {
// map any animal to its ID
if (obj is Animal) return ((Animal)obj).ID;
return obj;
}
public object GetDeserializedObject(object obj, Type targetType) {
// use the static accessor instead of a constructor!
if (targetType == typeof(Animal)) return Animal.GetAnimalById((int)obj);
}
}
BTW: DataContacts seem to have a bug (or is it a feature?) which causes them to act weirdly when the substitute type is a basic type. I've had such problem when serializing objeects as strings - the GetDeserializedObject method was never fired when deserializing them. If you run into this behaviour, use a wrapper class or struct around that single int field in the surrogate.
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.