Can I use generics to change a subclass' method signature? - c#

I need to perform an operation on a subclass and return a result:
public interface IEntity { }
public abstract class Entity : IEntity {
public abstract IEntity doStuff(IEntity e1, IEntity e2, IEntity e3);
}
public class Customer : Entity {
public override IEntity doStuff(IEntity e1, IEntity e2, IEntity e3) { // <-- yuck
var customer1 = e1 as Customer; // <-- yuck
var customer2 = e2 as Customer; // <-- yuck
var customer3 = e3 as Customer; // <-- yuck
// do stuff
return foo;
}
}
I want to avoid that subclass' method signature, and the associated typecasting.
So I prefer this:
public override Customer doStuff(Customer c1, Customer c2, Customer c3) {
// do stuff
return foo;
}
How would I use the type system to accomplish that?
EDIT: I changed the name of the method from compare to doStuff, to reiterate that the operation itself is irrelevant. I'm not trying to compare. I just want to change the types. How do I do that?
Many have said to change the design, but that I cannot do. I already have a solution, which I've included below, and it works. If you have a better way to accomplish this, without criticising the design (which is not the point), then please let me know. Thanks for everyone's contribution though.

This works. But the self-referencing generics make my head hurt.
public interface IEntity { }
public abstract class Entity<TEntity> : IEntity where TEntity : IEntity {
public abstract TEntity doStuff(TEntity e1, TEntity e2, TEntity e3);
}
public class Customer : Entity<Customer> {
public override Customer doStuff(Customer c1, Customer c2, Customer c3) {
// do stuff
return foo;
}
}
Is this a good solution, or are there gotchas in there that'll give me problems?
Is there a better solution?

In the prospect of persistance ignorance, serialization (JSON/XML) and binarization for network transmission, you may be better off without the interface.
To distinguish from POCO classes which are also called entities I prefer the original term "Domain Object" as given in Eric Evans' original work.
This is just an example on what I would do.
public abstract class AbstractDomainObject<T>
where T : AbstractDomainObject
{
public abstract bool CanDoStuffWith(T other);
}
public class Customer : AbstractDomainObject<Customer>
{
public override bool CanDoStuffWith(Customer other)
{
return this.Gender != other.Gender;
}
}

The reason why this is coming across as confusing is that this
public abstract class Entity : IEntity {
public abstract IEntity doStuff(IEntity e1, IEntity e2, IEntity e3);
}
shouldn't implement IEntity. If you need a class that "does stuff" with an IEntity then that's separate from an IEntity. That's the Single Responsibility Principle. Unless the primary purpose of an IEntity is to doStuff then doStuff wouldn't be in the same class.
Whatever doStuff does, that's what this class should be. For example, if it compares whether instances of IEntity are compatible for some operation, you might do this:
public interface ICompatibilityChecker<TEntity> where TEntity : IEntity
{
bool AreCompatible(TEntity entity, TEntity other);
}
Then you might find that you don't even need an abstract class:
public class CompatibilityChecker : ICompatibilityChecker<Customer>
{
public bool AreCompatible(Customer entity, Customer other)
{
//check compatibility
}
}
Another principle involved is Favor Composition Over Inheritance. There's a tendency to want to put functionality into base classes when it often makes more sense to put it into entirely separate classes. But notice how when you separate out some of these behaviors into separate classes the design of those classes becomes much simpler.
Also, what if you have domain objects that don't need that behavior? Then the inheritance becomes more difficult because you might need other methods in the abstract class but you're stuck implementing another one that you don't even need.
More often than not when we try to share functionality between classes by having them inherit from common base classes it gets convoluted and eventually breaks down. It's much easier to maintain if we separate behaviors and responsibilities into separate classes.

Related

How o restrict Generic type implementations in c#

I'm wondering if there is a way to constrain the implementations of a generic type by asking Not to implement a specific interface
Something like
public class PrivateGarage<TVehicle> where TVehicle : **not** Itruck
{
...
}
This might works but it's less elegant
public class PrivateGarage<TVehicle>
{
public PrivateGarage()
{
if(typeof(TVehicle) is Itruck)
{
throw new ArgumentException("Truck is not a valid type for private garage");
}
}
}
There is an approach you can take to solve this, but it only works well if there is only one discriminant to worry about.
Let's suppose the base interface is IVehicle:
public interface IVehicle
{
public void Park();
}
In your case, the discriminant is whether or not the vehicle can go in the garage, i.e., is it a "private vehicle"?
The following two interfaces can represent the discriminant:
public interface ICommercialVehicle: IVehicle
{
}
public interface IPrivateVehicle: IVehicle
{
}
Now you can represent a private garage by requiring IPrivateVehicle rather than IVehicle:
public class PrivateGarage<T> where T: IPrivateVehicle
{
readonly List<IPrivateVehicle> _vehicles = new();
public void Park(T vehicle)
{
_vehicles.Add(vehicle);
}
}
Suppose you also have a Truck type that does not inherit directly or indirectly from IPrivateVehicle. In that case if you try to create a PrivateGarage<Truck> you'll get a compile error.
This approach does not scale at all well, so it's probably better to take the approach of using properties and checking them at runtime.
A slightly different approach is to use interfaces as "Tags". I must stress that this is considered by many to be a bad design.
To do that you'd use an IPrivateVehicle tag as a kind of attribute.
Then the hierarchy would be like this:
public interface IVehicle
{
public void Park();
}
public interface IPrivateVehicle {} // Tag interface. Considered bad design.
public class PrivateGarage<T> where T: IPrivateVehicle, IVehicle
{
readonly List<IVehicle> _vehicles = new();
public void Park(T vehicle)
{
_vehicles.Add(vehicle);
}
}
public interface ICar: IVehicle, IPrivateVehicle
{
}
public interface ITruck : IVehicle
{
}
Then if you had concrete classes implementing ICar and ITruck called Car and Truck respectively:
var carGarage = new PrivateGarage<Car>(); // Compiles
var truckGarage = new PrivateGarage<Truck>(); // Does not compile.
An advantage of this approach is that you can use many tags.
An disadvantage of this approach is that you can use many tags. ;)
No, there isn't. The only way to specify constraints is inclusive. There is no way to exclude specific subtypes. See the documentation for the list of permitted types of constraints.
The reason, most likely, is such a constraint would break polymorphism. If it were possible, it would mean that instances of a specific descendant of the actual type parameter, and its all descendants would, could not be passed to the generic class.
A possible alternate way to impose such a constraint is to introduce properties at an IVehicle interface such as:
public interface IVehicle
{
bool CanCarryPassengers { get; }
bool CanCarryCargo { get; }
}
However, there's much more to check for a hypothetical PrivateGarage, so in the reality, the conditional to allow a particular vehicle in the garage would be much more complicated than a simple negative constraint.
No, there is no weay to exclude a type, constraints don't work that way.
A common solution would be to have an interface specifically for this, like IVehicleThatCanGoInGarage, which may itself also implement IVehicle
public interface IVehicleThatCanGoInGarage : IVehicle
{}
public class PrivateGarage<TVehicle> where TVehicle : IVehicleThatCanGoInGarage
{
...
}

Purpose of IAggregateRoot interface in in Microsoft Repository Pattern document

I am looking at the Respository Pattern in Microsoft website.
Respository Pattern
I section i am not understand what IAggregateRoot does?
public interface IRepository<T> where T : IAggregateRoot
{
//....
}
Can each respository class interact each others e.g. Product respository may be used by OrderRespository.
TL;DR:
The IAggregateRoot interface doesn't really do anything except mark classes that are aggregate roots so that if a class doesn't implement that interface,
public class Repository<NotARootAggregate> : IRepository<NotARootAggregate>
...won't compile. It helps us not to create a repository for a class that isn't an aggregate root.
That generic constraint is just a way of preventing the creation of repository for something that isn't an aggregate root.
What is an aggregate root and why does it matter when we're creating a repository? Here's a really contrived example:
public interface IAggregateRoot { }
public enum TreeType
{
Apple, Lemon
}
public class Fruit
{
public Fruit(TreeType fruitType) { FruitType = fruitType; }
public TreeType FruitType { get; }
}
public class TreeBranch
{
private List<Fruit> fruitOnBranch = new List<Fruit>();
public TreeBranch(TreeType branchType) { BranchType = branchType; }
public TreeType BranchType { get; }
public void AddFruit(Fruit fruit)
{
if (fruit.FruitType != BranchType)
{
throw new ArgumentException("Wrong type of fruit!");
}
fruitOnBranch.Add(fruit);
}
}
public class Tree : IAggregateRoot
{
private List<TreeBranch> branches = new List<TreeBranch>();
public Tree(TreeType treeType) { TreeType = treeType; }
TreeType TreeType { get; }
public void AddBranch(TreeBranch branch)
{
if(branch.BranchType != TreeType)
{
throw new ArgumentException("Wrong type of branch!");
}
branches.Add(branch);
}
}
It's designed so that it's impossible to add the wrong kind of branch to a tree or the wrong kind of fruit to a branch. So it's impossible to add a lemon to an apple tree. It's also impossible to change a lemon into an apple. The code enforces the rule that the right fruit grows on the right tree.
Having the tree as the aggregate root means that we're only going to save the tree to the database along with its branches and fruit. We'll never save just the branches or fruit. As long as we enforce that, we won't accidentally add lemons to apple trees.
If we defined a FruitRepository then we could accidentally go around that and save incorrect fruit.
So declaring the repository with that generic constraint:
public interface IRepository<T> where T : IAggregateRoot
^^^^^^^^^^^^^^^^^^^^^^^^
means that a class that implements the interface won't compile unless T implements IAggregateRoot.
So the only purpose of IAggregateRoot is to mark a class and say, "This is an aggregate root. It's okay to define a repository for it." That's why the documentation you referenced calls it a "marker interface."
It's a little bit weird because you could just put that interface on Fruit or TreeBranch, and then you'd be able to create a repository for them. Nothing will stop you from doing that. But the idea is that you or someone else will know not to do that. (But if you already knew not to do that, then you didn't need the IAggregateRoot interface to stop you from creating the repository, right?) So it's a slightly weak guard against making a mistake.

Generic repository issue with inheritance

I have N-Layer solution in .Net with PetaPoco as microORM. I get the entities generated from the template generator of PetaPoco. These entities T derive from the base class Record<T>. Then I extend them adding more data access facilities and custom Save() and Delete() methods that override the Record<T> default methods.
Following is the overrided Delete method from the entity (the method I want to call)
public partial class Document : Record<Document>
{
public new int Delete()
{
int rowsAffected;
using (var uow = DB.GetInstance().GetTransaction())
{
rowsAffected = base.Delete();
LogSystem("Deleting", "Deleting a document", 0, 0, GUID);
uow.Complete();
}
return rowsAffected;
}
}
Then when I create the generic repository the methods getting called are from the base class Record<T> and not my custom ones from the entities. When I call an entityRepository.Delete() method, the Delete() method from my entity should get called and not the one from the default Record<T> class.
The generic repository class is as follwos:
public abstract class GenericRepository<T> : IGenericRepository<T> where T : Record<T>, new()
{
public void Delete(T entity)
{
entity.Delete();
}
}
The cause of this problem is that in your GenericRepository you specify T as "something deriving from Record". So wenn calling entity.Delete(), this call will be linked to this base method, since this is only done once for all possible instances of T.
If you have access to the Record<T> class, just make the Delete() method virtual and override it in Document.
If not, try using something like this:
public class ExtendedRecord<T>: Record<T>
{
public virtual new int Delete()
{
base.Delete();
}
}
public partial class Document : ExtendedRecord<Document>
{
public override int Delete()
{
// ...
}
}
public abstract class GenericRepository<T> : IGenericRepository<T>
where T : ExtendedRecord<T>, new()
{
// ...
}
Confession: I have no knowledge of PetaPoco and its template generator.
The problem is more related to OO (specifically Inheritance) than PetaPoco IMHO. If generic repository is created with Record<T> which is also a base class for each entity, then what happening is as expected. You need to closely look into inheritance of your classes.
You may need to make few changes in the solution I am proposing below to match up with ORM functionality.
Solution 1:
Declare a new base class or interface something like below:
public interface IEntityBase{.....
Include the necessary members like Delete method in interface.
Then, derive each entity from this interface as well:
public partial class Document : Record<Document>, IEntityBase
Then, create a generic repository with this interface instead of Record<T> something like below:
public abstract class GenericRepository<T> : IGenericRepository<T> where T : IEntityBase
This way, you achieve your objective without changing much of your existing code.
Solution 2:
Another dirty solution is to cast the Record<T> to its actual instance.
public void Delete(T entity)
{
if(typeof(T) == typeof(Document))
Document myEntity = (Document)entity;
myEntity.Delete();
}
Casting in each method is definitely bad idea. Look for some better centralized location in your code. I just wanted to show you the way.
Solution 3:
Other thought is to make Delete method in Record<T> a virtual method. But I am not sure how your ORM works or even if your ORM allows this, so I will not comment on this.

In EF6, how to create a generic method to get entities using a common field/column

im sorry if the title isnt enlightening enough after a while i couldnt come with a phrase to explain my problem.
Its like this:
I'm using EF6, Database first approach. All my entities have an ID and an Enabled property.
I have the EDMX file on my DAL and now i need to design the Business Layer (BLL for me).
Since i will need to validate what data comes from the DAL and is visible to the rest of the app i decided to create an interface for the common operators, create a base class that implements that and have all my custom database-tables\entities providers inherit that.
If that doesnt make sense, here is what i'm doing: (All of this is in BLL)
public interface IEntityManager<T> where T : class {
void Add(T e, bool commit=false);
void Delete(T e);
void DeleteByID(int id);
void Update(T e);
IQueryable<T> Search(Expression<Func<T, bool>> predicate);
IQueryable<T> GetAll();
T Get(int id);
}
Now, the base class that implements the common operations is this: (edited for readability and brevity)
public class EntityManager<TEntity> : IDisposable, IEntityManager<TEntity> where TEntity : class {
private readonly DbContext _ctx;
private readonly DbSet<TEntity> _set;
public EntityManager() {
_ctx = new DomainModelFactory();
_set = _ctx.Set<TEntity>();
}
public void Add(TEntity e) {
_set.AddOrUpdate(e);
}
//other methods here
public TEntity Get(int id) {
return _set.Find(id);
}
}
To create managers that will actually access the data and make it usable across the application, i'm planning on doing something like:
public class VenueManager: EntityManager<Venue> {
public VenueManager():base() {
}
}
For the class that will manage my Venue entity. I am creating classes instead of using something like
var venueManager = new EntityManager<Venue>();
because these classes will have some specialized methods.
I hope you could understand what i have done so far (and it works)
Now, my problem is that every entity has two common fields: ID (int) and Enabled (bool)
I am to use these when deleting by id and when coding Get and GetAll because i must only
get items that have Enabled=true. Now, i know that since i'm create Manager classes i could just use c&p the code, but i was wondering, is there a way that i can code this in the EntityManager class and have all the managers inherit the method but using the concrete classes ?
something like this:
In EntityManager class:
public TEntity Get(int id) {
return _set.Where(T.ID==id);
}
Thats basically what i want: a way to use these properties at the base class (EntityManager) where they matter (methods deletebyid, get and getall) in a way that all Manager classes (ManagerVenue in the example) inherit these methods so that i wont have to write them all over and over? (got some 100 entities)
You should define a base class or interface for all your entities, something like:
public class Entity {
public int Id { get; set; }
public bool Enabled { get; set; }
}
And in your EntityManager class add a generic constraint to TEntity like where TEntity : Entity
Then you will be able to use the common properties Id and Enabled inside your base class EntityManager.

Best way to refer to my own type

abstract class A<T> where T:A<T>
{
public event Action<T> Event1;
}
class B : A<B>
{
//has a field called Action<B> Event1;
}
Is there a more elegant way to do this? I want stuff (events, etc) in the base class to be able to use the subclass' type.
The pattern you are using does not actually implement the constraint you want. Suppose you want to model "an animal can only be friendly with something of its own kind":
abstract class Animal<T> where T : Animal<T>
{
public abstract void GetFriendly(T t);
}
class Cat : Animal<Cat>
{
public override void GetFriendly(Cat cat) {}
}
Have we succeeded in implementing the desired constraint? No.
class EvilDog : Animal<Cat>
{
public override void GetFriendly(Cat cat) {}
}
Now an evil dog can be friendly with any Cat, and not friendly with other evil dogs.
The type constraint you want is not possible in the C# type system. Try Haskell if you need this sort of constraint enforced by the type system.
See my article on this subject for more details:
http://blogs.msdn.com/b/ericlippert/archive/2011/02/03/curiouser-and-curiouser.aspx
What you have works very well. In fact it's very similar to other .NET interfaces and types where you want the interface implementer to use your type, like:
public class MyClass : IEqualityComparer<MyClass>
{
// From the interface IEqualityComparer
public bool Equals(MyClass other) { ... }
...
}
I don't think you need to specify where T:A.
T will be B when you use class B:A
This is also known as CRTP or Curiously recurring template pattern and is a known idiom.
Since A is abstract, you can add abstract methods to A and invoke them from A and B, which will be forced to implement the method, will be the invoker:
abstract class A<T> where T:A
{
public event Action<T> Event1;
public abstract void Method();
public A(){Method();}
}
class B : A<B>
{
//has a field called Action<B> Event1;
public void Method(){ //stuff }
}
On instantiation of B, the base class constructor will call Method() which is only implemented in B, forcing B's instance to be called.
This allows A to invoke subclass specific methods without requiring A to have specific knowledge of Children. The downside is that ALL children must implement Method or re-abstract it to their own children.
My most recent question was marked as a duplicate of this one. I totally agree on that matter. So I came here to take a look at the answers and to read Eric's post on that (very interesting indeed). You can not enforce this at compile time with the type system but you can do this at runtime. The way I implemented this is:
abstract class FooBase<T>
{
protected FooBase()
{
if (typeof(T) != GetType())
{
throw new InvalidOperationException();
}
}
}
By doing this we can plant the seed of an evil dog, but that dog will be aborted at runtime.

Categories