Where Generic T is implementation of Abstract Class - c#

Given the following classes and hierarchy:
public abstract class AbsractClass<T>
{
public T Id { get; private set; }
}
public class ImplementationA : AbsractClass<Guid> { }
public class ImplementationB : AbsractClass<int> { }
What constraint should I be using in where clause/constraint to specify that generic T must be implementation of AbsractClass. Which would mean that Entity would accept either ImplementationA or ImplementationB.
public abstract class Entity<T> // where : T ?
{
}
Is this something that is possible or should I be using interfaces instead?

You need to add two generic parameters to make it work:
public abstract class Entity<T, TKey> where T : AbstractClass<TKey>
{
}
Generic interfaces would behave the same way.

Related

Incorrect number of type parameters in reference class MyClass<F,T> - Generic entity framework

I've got the following generic abstract class:
public abstract class MyClass<F, T>
where TCurrencyFrom : Book
where TCurrencyTo : Book
{
public int Id { get; set; }
public virtual F First{ get; set; }
public virtual T Second { get; set; }
}
And I got 3 classes which implement this class like:
public class Implementation1 : MyClass<BookType1, BookType2>
{
}
public class Implementation2 : MyClass<BookType2, BookType1>
{
}
Now I got an "EntityTypeConfiguration" for those which looks like:
public class MyClassConfiguration<TMyClass> : EntityTypeConfiguration<TMyClass> where TMyClass: MyClass
{
public MyClassConfiguration()
{
...
}
}
And try to use those like:
public class Implementation1Map : MyClassConfiguration<Implementation1>
{
public Implementation1Map ()
{
...
}
}
But then I get the following error:
Incorrect number of type parameters in reference class MyClass
How can I solve this problem and make sure I have a generic approach on the EntityTypeConfigurations?
Unfortunately this is tricky with .NET generics.
If MyClassConfiguration doesn't actually care about the type arguments, you might want to create a non-generic interface:
public interface IMyClass
{
// Any members of MyClass<,> which don't rely on the type arguments,
// e.g. the Id property
}
Then make MyClass<,> implement IMyClass:
// Type parameters renamed to make the type constraints sensible...
public abstract class MyClass<TCurrencyFrom, TCurrencyTo> : IMyClass
where TCurrencyFrom : Book
where TCurrencyTo : Book
And change the type constraint for MyClassConfiguration:
public class MyClassConfiguration<TMyClass> : EntityTypeConfiguration<TMyClass>
where TMyClass: IMyClass
(Obviously you'll want to give IMyClass a more useful name...)
Alternatively, just make MyClassConfiguration generic in three type parameters:
public class MyClassConfiguration<TMyClass, TCurrencyFrom, TCurrencyTo>
: EntityTypeConfiguration<TMyClass>
where TMyClass: MyClass<TCurrencyFrom, TCurrencyTo>
where TCurrencyFrom : Book
where TCurrencyTo : Book
public class Implementation1Map
: MyClassConfiguration<Implementation1, BookType1, BookType2>
public class Implementation2Map
: MyClassConfiguration<Implementation2, BookType2, BookType1>
It's ugly, but it'll work.

4 Classes with the same properties and methods - is it possible to create only one?

i have another question open here on SO and after thinking about it, i may be approaching this in the wrong way.
i have 4 classes, that have the same properties and methods.
some of the classes, have their own properties and methods ( not overrides of the existing ones ).
currently i create each class as:
public class ClassOne
{
public ClassOne()
{
}
public int ID {get;set;}
// More properties here
public void Set(){
// Do Stuff to save this
}
// More Methods here
}
cant i create one class that will generate all of the 4 classes?
and in the classes themselfs i only create specific properties/methods for that class?
repeating the code seems very odd to me, im sure there must be a way to do this, just dont know how.
Your situation is one of the main reasons why inheritance was invented. So with that, you can write
public class Base
{
// Properties and methods common to all
}
public class ClassOne : Base
{
// Properties and methods specific to ClassOne
}
public class ClassTwo : Base
{
// Properties and methods specific to ClassTwo
}
public class ClassThree : Base
{
// Properties and methods specific to ClassThree
}
public class ClassFour : Base
{
// Properties and methods specific to ClassFour
}
As requested, more code, using interfaces and abstract classes:
An interface is just a blueprint, defining what properties and methods are required to be compatible with other "BaseClasses"
public interface IBaseClass
{
public int ID {get;set;}
public void Set();
}
Abstract classes can contain code, but can not be instantiated, they are form of starting point for a class, but not a complete class themselves.
public abstract class ABaseClass : IBaseClass
{
public int ID {get;set;}
public void Set(){
// Do Stuff to save
}
}
Each class inherits from the abstract class and can then override and implement whatever it wants, customizing it however is necessary.
public class ClassOne : ABaseClass
{
}
public class ClassTwo : ABaseClass
{
}
public class ClassThree : ABaseClass
{
}
public class ClassFour : ABaseClass
{
}
ps. not entirely sure if my syntax is 100% correct
Could you simply make a base class with your properties and inherit from that class?
Why not use inheritance??
public class ClassOne
{
public ClassOne()
{
}
public virtual int ID {get;set;}
// More properties here
public virtual void Set(){
// Do Stuff to save this
}
// More Methods here }
public class ClassTwo : ClassOne
{
public string ClassTwoString { get; set; }
}
public class ClassThree : ClassOne
{
public string ClassThreeString { get; set; }
}
Can you make them all inherit off of the same class? If so, that sounds ideal.
Barring the possibility of making them inherit, you could write an interface that describes the methods and properties which each of them use. Then you can call each instance of the class through the same interface.
Barring again that possibility, you could write a reflective assignor/accessor. But you shouldn't do that.

How do I use a generic base class two levels down in an inheritance tree?

Imagine that I have a generic base class like this:
public abstract class AnimalDTO<TA, TB>
{
public static TB ToDTO(TA entity)
{
return ConvertToDTO<TB>(entity);
}
}
The class is responsible for being able to convert a passed-in entity to a DTO.
I have a class that uses this generic class:
public class MammalDTO<Mammal, MammalDTO>
{
// omitted stuff here
}
A user can now use MammalDTO.ToDTO(mammal) to convert a Mammal to a MammalDTO.
Now I want to derive off Mammal:
public class Koala<???, ???> : Mammal<???, ???>
How do I do this?
One solution would be to makeMammalDTOan open but constrained generic type.
You could then try to constrain the generic further and further as you go down the inheritance hierarchy, closing it at a leaf. It may also be suitable to use abstract classes as appropriate, but this is not a requirement of the pattern.
To be honest though, I don't really like the 'self-referencing generic' pattern; I find it quite confusing.
public abstract class Animal { }
public abstract class Mammal : Animal { }
public sealed class Koala : Mammal { }
public abstract class AnimalDTO<TAnimal, TDTO> where TAnimal : Animal
{
public abstract TDTO ConvertToDTO(TAnimal entity);
}
public abstract class MammalDTO<TMammal, TMammalDTO> : AnimalDTO<TMammal, TMammalDTO>
where TMammal : Mammal
where TMammalDTO : MammalDTO<TMammal, TMammalDTO>{}
public sealed class KoalaDTO : MammalDTO<Koala, KoalaDTO>
{
public override KoalaDTO ConvertToDTO(Koala entity)
{
throw new NotImplementedException();
}
}

C#: Generic implementation of method doesn't satisfy interface

In this post I talked about using a generic base class to enable me to create repository classes without duplicating loads of basic plumbing code.
Each Repository is accessed through an interface. In the code below, I will only show one of the methods for the sake of brevity:
Interface:
IQueryable<Suggestion> All { get; }
Generic base class
public IQueryable<T> All
{
get { return _unitOfWork.GetList<T>(); }
}
Concrete class (implements the interface and extends the generic base class)
public IQueryable<Suggestion> All
{
get { return _unitOfWork.GetList<Suggestion>(); }
}
I anticipated that I would be able to simply strip the method out of the concrete class, and the compiler would use the generic base class implementation instead and work out that was intended to satisfy the interface. But no!
When I strip the method out I get the old 'does not implement interface member' error.
If I can't do this, have my efforts to use a generic base class not been pointless? Or is there a way around this?
Can you make the interface itself generic then implement a typed version in your concrete class?
public interface IRepository<T>
{
List<T> All { get; }
}
public class Repository<T>
{
public List<T> All
{
get { return new List<T>(); }
}
}
public class SuggestionRepository : Repository<Suggestion>, IRepository<Suggestion>
{ }
I'd still suggest using the generic interface since it will save you from repeating yourself, but this works too.
public interface ISuggestionRepository
{
List<Suggestion> All { get; }
}
public class Repository<T>
{
public List<T> All
{
get { return new List<T>(); }
}
}
public class SuggestionRepository : Repository<Suggestion>, ISuggestionRepository
{ }
Use the virtual keyword and put your interface on your concrete implementation..
public interface IMyInterface<T>
{
IQueryable<T> All { get; }
}
public abstract class MyBaseClass<T> : IMyInterface<T>
{
public virtual IQueryable<T> All
{
get { return _unitOfWork.GetList<T>(); ; }
}
}
public class MyClass : MyBaseClass<Suggestion>, IMyInterface<Suggestion>
{
}

How to declare a generic constraint that is a generic type

I have a two generic abstract types: Entity and Association.
Let's say Entity looks like this:
public class Entity<TId>
{
//...
}
and Association looks like this:
public class Association<TEntity, TEntity2>
{
//...
}
How do I constrain Association so they can be of any Entity?
I can accomplish it by the following:
public class Association<TEntity, TId, TEntity2, TId2>
where TEntity : Entity<TId>
where TEntity2: Entity<TId2>
{
//...
}
This gets very tedious as more types derive from Association, because I have to keep passing down TId and TId2. Is there a simpler way to do this, besides just removing the constraint?
This problem is usually solved by having your generic class (Entity<TId>, in this case) inherit from a common non-generic class.
public abstract class EntityBase
{
}
public class Entity<TId> : EntityBase
{
}
This will allow you to do:
public class Association<TEntity, TEntity2>
where TEntity : EntityBase
where TEntity2 : EntityBase
{
}
Edit
If having them inherit from a common class is an issue, then this could be easily done with an interface as well.
If the Id types are important inside the Association definition, you could create an enclosing "context":
public static partial class EntityIds<TId1, TId2> {
public class Association<TEntity1, TEntity2>
where TEntity1 : Entity<TId1>
where TEntity2 : Entity<TId2>
{
// ...
}
}
This way, the Association class declaration is still intelligible, and it retains the necessary type arguments for its type parameters.
A factory method could help you with the normal case:
public static class AssociationFactory {
public static EntityIds<TId1, TId2>.Association<Entity<TId1>, Entity<TId2>> Create<TId1, TId2>(/*params...*/) {
return new EntityIds<TId1, TId2>.Association<Entity<TId1>, Entity<TId2>>(/*params...*/);
}
}
It that looks like too much, and if you don't have entity specializations, you could model the association differently:
public class Association<TId1, TId2>
{
// ...
Entity<TId1> Entity1 { get; set; }
Entity<TId2> Entity2 { get; set; }
// ...
}

Categories

Resources