C# Generic Repository - c#

I am trying to implement a generic repository but I am snagged. Here is a summary of my object model. The problem is that the concrete repository, "UserAccountRepositoryStub" will not compile. The error is:
The type User has to be convertible to type IRepository...
IRepostory:
public interface IRepository<T> where T : IEntity
{
...
}
Abstract Repository:
public class AbstractRepository<T> where T : class, IEntity, IRepository<T> {...}
IUserAccountRepository:
public interface IUserAccountRepository
User:
public class User : IEntity{...}
UserRepositoryStub(concrete):
public class UserAccoutRepositoryStub : AbstractRepository<User>, IUserAccountRepository

The definition of AbstractRepository<T> should probably be
public class AbstractRepository<T> : IRepository<T> where T : class, IEntity {...}
because you want the repository to implement IRepository<T> not the objects in it, right?

Your AbstractRepository requires that T is of type IRepository<T>. Did you mean to do:
public class AbstractRepository<T> : IRepository<T> where T : class, IEntity, {...}

On your AbstractRepository you've got the IRepository in the wrong spot. Everything after the "where" and before the "{...}" specifies the generic constraints. To specify inheritence you need to put it before the where.
Try this instead
public class AbstractRepository<T> : IRepository<T> where T : class, IEntity {...}

Related

How to reuse generic interface?

I'm using ASP.NET Boilerplate, on ASP.NET Core.
I have some model classes.
public class AClass : FullAuditedEntity<int>
{
}
and one interface like below.
public interface ISomeInterface<T, TEntity> where T : BaseFileEntity where TEntity : class, IEntity<int>
{
}
Now If I add one extra model class like below.
public class BClass : FullAuditedEntity<string>
{
}
I have to define another interface for this change like below.
public interface ISomeInterface<T, TEntity> where T : BaseFileEntity where TEntity : class, IEntity<string>
{
}
So basically it's duplicate code. Is there any better way to do this?
Is it possible to declare your interface like the one below so you can pass the type to IEntity
public interface ISomeInterfaceB<T, TEntity, TK> where T : BaseFileEntity where TEntity : class, IEntity<TK> {
}
You can Change the interface to:
public interface ISomeInterface<T, TEntity, U> where T : BaseFileEntity where TEntity : class, IEntity<U>
{
}

Interface with generic type used as generic type within second interface

I have an interface that references accepts generic type:
public interface IEntity<TType>
I hope to pass a reference of this to a second interface that takes a generic type:
public interface IRepository<T> : IDisposable where T : IEntity, new()
I have tried getting this to work but have so far failed to have it build.
Is there any way this can be done?
Your interface is IEntity<T>, not IEntity. This means that the signature of your IRepository needs to reflect this:
public interface IEntity<TType>
public interface IRepository<T, TEntity> : IDisposable where T : IEntity<TEntity>, new()

Generic base class where T is also a generic base class

I have a generic base class something like:
public abstract class SomeThingBase<T> where T : class
I'd like to have another base class something like this:
public abstract class MangerBase<T> where T : SomeThingBase<T>
How do you accomplish this in C#?
When trying to use ManagerBase like this it doesn't seem to work.
class TestManager : ManagerBase<TestSomething>
In order to do this you have to pass your generic declarations in all the way from the top. This can get very messy, so avoid doing it.
public abstract class SomeThingBase<T> where T : class{ }
public abstract class ManagerBase<T, U>
where T : SomeThingBase<U>
where U : class
{ }
It's definitely possible to define, but impossible to actually implement. Assuming you have the below definition:
public abstract class SomeThingBase<T> where T : class { }
public abstract class MangerBase<T> where T : SomeThingBase<T> { }
However, defining a class that implements ManagerBase<T> and SomethingBase<T> is impossible since multiple inheritance is not supported and T cannot meet both constraints without multiple inheritance the generic type.

How to Infer generic type from generic argument type of another argument

MVC has nothing to do with my problem. Don't get confused for the example. Its a pure C# problem
The title of the question is not well explaining the question I think.
Suppose, I have a base class for some entity classes called EntityBase
Some classes are like
class Entity1 : EntityBase
class Entity2 : EntityBase
I have an abstract Repository that works with basic operations on entities. The declaration is:
abstract class RepositoryBase<TEntity> where TEntity : EntityBase
And there are several implementations of this class
class Repository1 : RepositoryBase<Entity1>
class Repository2 : RepositoryBase<Entity2>
Now there are some controllers with a base:
public abstract class RepositoryControllerBase<TRepository, TEntity>
where TRepository : RepositoryBase<TEntity>
where TEntity : EntityBase
And implementations are like
class Controller1 : RepositoryControllerBase<Repository1, Entity1>
class Controller2 : RepositoryControllerBase<Repository2, Entity2>
Now, you must have noticed that, When the type of repository in a controller is Repository1, The entity type must be Entity1. Otherwise it will be a compilation error.
So, I think there is a way to skip the second generic type and automatically infer that one. I just do not know how. Any suggestions?
Perhaps, the problem could be easily solved with ? if it was Java. Replacing ControllerBase declaration with
public abstract class RepositoryControllerBase<TRepository>
where TRepository : RepositoryBase<?>
There is no constraint type inference for a reason: http://blogs.msdn.com/b/ericlippert/archive/2012/03/09/why-not-automatically-infer-constraints.aspx
Also, the obvious counterexample for your idea would be using interfaces:
interface IEntity1 : IEntityBase {}
interface IEntity2 : IEntityBase {}
interface IRepositoryBase<TEntity> where TEntity : class, IEntityBase {}
class Repository1 : RepositoryBase<IEntity1> {}
class Repository2 : RepositoryBase<IEntity2> {}
class Repository12 : IRepositoryBase<IEntity1>, IRepositoryBase<IEntity2> {}
public abstract class RepositoryControllerBase<TRepository, TEntity>
where TRepository : RepositoryBase<TEntity>
where TEntity : IEntityBase {}
class Controller1 : RepositoryControllerBase<Repository1, Entity1>
class Controller2 : RepositoryControllerBase<Repository2, Entity2>
class Controller12 : RepositoryControllerBase<Repository12, Entity1>
Without specifying an Entity1 type parameter in a Controller12 definition, what should a compiler check?

How to specify type constraint and inheritance on declaring class?

I've got an abstract class which has a type constraint. But i also want to make the abstract class implement an interface.
E.g:
public abstract class PostEvent<TPost> : IDomainEvent, where TPost : Post, new()
Which doesn't compile.
I don't want this:
public abstract class PostEvent<TPost> where TPost : Post, IDomainEvent, new()
Because that means TPost : IDomainEvent
I want PostEvent : IDomainEvent
What's the syntax?
Try this:
public abstract class PostEvent<TPost> : IDomainEvent where TPost : Post, new()
You don't want a comma between the interface list and the generic constraints.
You need to actually implement it (you can't leave the implementation purely to the concrete types - it needs to know where to start):
public abstract class PostEvent<TPost> : IDomainEvent
where TPost : Post, new()
{
public abstract void SomeInterfaceMethod();
}
You could also use an explicit interface implementation and protected abstract method if you don't want Otis on the public API:
public abstract class PostEvent<TPost> : IDomainEvent
where TPost : Post, new()
{
protected abstract void SomeInterfaceMethod();
void IDomainEvent.SomeInterfaceMethod() {
SomeInterfaceMethod(); // proxy to the protected abstract version
}
}

Categories

Resources