Repository Pattern with Generic interface and DI in EF - c#

i have this existing code
public interface IRepository<T>
{
void Create(T obj);
T Retrieve(string key);
}
public class ItemRepository : IRepository<Item>
{
public void Create(Item obj)
{
//codes
}
public Item Retrieve(string key)
{
//codes
}
}
i would like to create a General class repository where i have to inject a type of IRepository to the constructor then use its own implementation of the methods. i already have an existing code but it is currently wrong
public class Repository
{
IRepository<T> action = null;
public Repository(IRepository<T> concreteImplementation)
{
this.action = concreteImplementation;
}
public void Create(T obj)
{
action.Create(obj);
}
}
the classes are from EF. if there is no work around for this what will be the best approach?

If I understand you correctly you want a single repository which can create or retrieve an object of any type by delegating to a type specific repository implementation?
How do you imagine this working? you defined this Repository class, but you have to create a concrete implementation of the actual repository in order to use it, and then still have to create an instance of Repository anyway. Why not just use the generic implementation you have to create anyway?
And what about your Retrieve method? How will this look in your Repository class? Will you just return Object? or will you make your method generic?
Anyway to answer your question, you could do this I suppose:
public class Repository
{
IRepository action = null;
public Repository(IRepository concreteImplementation)
{
this.action = concreteImplementation;
}
public void Create<T>(T obj)
{
action.Create(obj);
}
}
but you have to introduce a non generic interface as well, as you can't require an interface with a generic parameter in the constructor without specifying the generic type on the class.
public interface IRepository
{
void Create(object obj);
object Retrieve(string key);
}
Or possibly you could pass in the type into the Create method instead of having a generic parameter:
public class Repository
{
IRepository action = null;
public Repository(IRepository concreteImplementation, Type respositoryType)
{
this.action = concreteImplementation;
expectedType=repositoryType;
}
public void Create(Type type, Object obj)
{
if(type==expected && obj.GetType()==type)
{
action.Create(obj);
}
}
}
but both of these are terrible ideas. Just use the generics and create a repository per type, it'll be best in the long run

I think you might just be missing the definition of T in the context of the general repository class.
Try adding <T> to the it like this:
public class Repository<T>
{
...
}

Related

How could I show methods depending of the generic entity of a class?

I want to create methods that only will able to use if the generic type of a class is from a specific type.
For example, I have two abstract classes NamedEntity and KeyedEntity and I have a class which works with a generic type: MyClass<T>
I would like to create a method X on MyClass<T> which only will be able if the T is a NamedEntity and a method Y on MyClass<T> which only will be able if T is a KeyedEntity. If T is both, both methods will be shown.
I don't want to implement the method independently of the generic type and thrown an error if the type is not the correct type to use the method, but if this is the only way I will do.
If I could inherit from multiple classes it would be easy, but how C#only allow me to inherit from one class it is being hard to think about for me.
EDIT
I agree with all your points. I will try to explain better:
I have an abstract service class, which could work with all the database entities of my system.
All entities could have the "default" methods like "GetById(long id); Create(T entity); Update(T entity)" and it's possible because I am working with an ORM (Nhibernate).
I would like to create the method "GetByName" but not all of the entities have the property "Name", so it will be better if the method GetByName appears only for services which works with a Generic Type that force the entity to have the property "Name", this Generic Type should be the entity class, if I use interfaces (INamedEntity, IKeyedEntity) the problem continue being the same.
If I'm understanding you correctly, you are trying to achieve something like the following (non compilable code follows):
class MyClass<T>
{
public void X(T t) where T: NamedEntity { ... }
public void X(T t) where T: KeyedEntitiy { ... }
}
This won't compile You can not constrain T at method level, only at class level.
Ok. Constraining at top level seems useless, because you'd need to constrain to both NamedEntity and KeyedEntity which is self defeating, so let's constrain at method level:
class MyClass<T>
{
public void X<Q>(Q q) where Q: NamedEntity { ... }
public void X<Q>(Q q) where Q: KeyedEntitiy { ... }
}
Now this won't compile because constraints on generic type parameters are not part of a method's signature. The two methods X would essentially be the same overload and therefore the compiler will flag the second method with an error; method X already exists....
Also, you'd need to check that Q and T are actually compatible and this will only be possible at runtime, not at compile time...yuck!
Ok, then the only option seems to be overloading:
public X(NamedEntity entity) { ... }
public X(KeyedEntity entity) { ... }
Of course this is also far from safe at compile time; you still need to check that the right method is called for the actual type of T and this check can only be done at runtime. Yuck again...
Also, what happens if you have the following:
class Foo: NamedEntity, KeyedEntity { }
myClass.X(new foo()); //now what? What X is called?
This whole setup just seems completely off, you should rethink you approach or give more information on what exactly is it you are trying to achieve.
UPDATE Ok, all clearer now. The methods dont share the same name, thats a big difference!
Based on new info in your question, I would recommend the following approach:
public interface IKeyedIdentity
{
long Id { get; }
}
public interface INamedIdentity: IKeyedIdentity
{
string Name { get; }
}
public class MyClass<T> where T: IKeyedIdentity
{
public void Create(T entity) { ... }
public void Update(T entity) { ... }
public T GetById(long id) { ... }
public Q GetByName<Q>(string name)
where Q : T, INamedEntity
{ ... }
}
Here it makes sense to make the method generic itself because there is a relationship between T and Q you can leverage. This wasn't altogether clear before.
Downside, you have to explicitly supply Q in calls to GetName, I can't think of any compile time safe set up that would avoid this.
UPDATE #2: I think you have to take a step back and implement specialized MyClass<T>s that know how to deal with each expected entity type.
Consider the following code, it should give you enough ideas to implement a similar pattern in your particular scenario:
public static class EntityManagerProvider
{
public static EntityManager<Q> GetManager<Q>()
{
if (typeof(INamedIdentity).IsAssignableFrom(typeof(Q)))
return typeof(NamedEntityManager<>).MakeGenericType(typeof(Q)).GetConstructor(new Type[] { }).Invoke(new Type[] { }) as MyClass<Q>;
if (typeof(IKeyedIdentity).IsAssignableFrom(typeof(Q)))
return typeof(KeyedEntityManager<>).MakeGenericType(typeof(Q)).GetConstructor(new Type[] { }).Invoke(new Type[] { }) as MyClass<Q>;
return null;
}
public abstract class EntityManager<T>
{
public void Create(T entity) { ... }
public void Update(T entity) { ... }
public abstract T GetById(long id);
public abstract T GetByName(string name);
}
private class KeyedEntityManager<Q> : EntityManager<Q> where Q : IKeyedIdentity
{
public override Q GetById(long id) { return default(Q); }
public override Q GetByName(string name) { throw new NotSupportedException(); }
}
private class NamedEntityManager<Q> : EntityManager<Q> where Q : INamedIdentity
{
public override Q GetById(long id) { throw new NotSupportedException(); }
public override Q GetByName(string name) { return default(Q); }
}
}
Now you can do the following:
var myNamedFooManager = MyClassProvider.GetMyClass<NamedFoo>();
var namedFoo = myNamedFooManager.GetByName("Foo"); //I know this call is safe.
var myKeyedFooManager = MyClassProvider.GetMyClass<KeyedFoo>();
var keyedFoo = myNamedFooManager.GetById(0); //I know this call is safe.
Downside: if you need to interact with a given entity that is both keyed and named in either way, you'll have to use two distinct managers.

Generic class with non-generic method constraint?

I have this class working as my repository:
public class Repository<T> where T : class, new()
{
public T GetByID(int id)
{
//Code...
}
}
But there a few cases where I don't want to leave a class' default public constructor (such as some specific model properties that require some logic), like this:
public class Person
{
public CPersonID PersonID { get; private set; }
//This shouldn't exist outside Person, and only Person knows the rules how to handle this
public class CPersonID
{
internal CPersonID() { }
}
}
This makes the Repository template class invalid because of the new() constraint.
I'd like to make something like this:
public class Repository<T> where T : class
{
//This function should be created only when the T has new()
public GetByID(int id) where T : new()
{
}
//And this could be the alternative if it doesn't have new()
public GetByID(T element, int id)
{
}
}
Is there any way I can accomplish this?
Edit: Example of a Get method:
public IList<T> GetAll()
{
IList<T> list = new List<T>();
using(IConnection cn = ConnectionFactory.GetConnection())
{
ICommand cm = cn.GetCommand();
cm.CommandText = "Query";
using (IDataReader dr = cm.ExecuteReader())
{
while(dr.Read())
{
T obj = new T(); //because of this line the class won't compile if I don't have the new() constraint
//a mapping function I made to fill it's properties
LoadObj(obj, dr);
list.Add(obj);
}
}
}
return list;
}
As Lasse V. Karlsen already answered, this is not directly possible. However, you can get very close, close enough for practical purposes.
Given public class Repository<T> where T : class, you cannot define instance methods that only exist when T has a parameterless constructor. You don't need that. You just need repository.GetByID(3) to work. That can work if GetByID is an instance method, but also if it is an extension method, and extension methods can add requirements to T.
public static class RepositoryExtensions
{
public T GetByID(this Repository<T> repo, int id) where T : class, new()
{
...
}
}
Note that extension methods don't work if an instance method of the same name already exists, so if you go with this, you need both overloads of GetByID to be extension methods, not just this one.
The actual logic belongs in the Repository class, but you can forward to that:
public class Repository<T> where T : class
{
internal T GetByIDImpl(int id, Func<T> factory)
{
...
}
}
public static class RepositoryExtensions
{
public T GetByID(this Repository<T> repo, int id) where T : class, new()
{
return repo.GetByIDImpl(id, () => new T());
}
public T GetByID(this Repository<T> repo, T element, int id) where T : class
{
return repo.GetByIDImpl(id, () => element);
}
}
No, you can't do it this way.
All constraints have to be specified the place where you introduce the generic parameter, in this case at the class level.
As such you have two options:
Add , new() as a constraint, limiting the use of the repository class to use types that have a public parameterless constructor
Not add it as a constraint, and use reflection to try to construct the object at runtime
Note that point 2 there may fail (at runtime) if the type does not have a valid constructor.
There is no way you can ask the compiler to create a class where the ability to call a specific method is conditional, ie. "Only let me call GetByID if the type has a constructor".
If you want it as a compile-time constraint, you can do
public class Class<T> where T : class
{
public void Method<U> where U : T, new()
{
// ...
}
}
but this has the disadvantage that you'd have to do
new Class<HasConstructor>().Method<HasConstructor>();
as the type won't be implicitly picked up. The advantage is that the following won't compile:
new Class<NoConstructor>().Method<NoConstructor>();

Overloading generic methods

When calling a generic method for storing an object there are occasionally needs to handle a specific type differently. I know that you can't overload based on constraints, but any other alternative seems to present its own problems.
public bool Save<T>(T entity) where T : class
{ ... some storage logic ... }
What I would LIKE to do is something like the following:
public bool Save<SpecificClass>(T entity)
{ ... special logic ... }
In the past our team has created 'one-off' methods for saving these classes as follows:
public bool SaveSpecificClass(SpecificClass sc)
{ ... special logic ... }
However, if you don't KNOW that function exists, and you try to use the generic (Save) then you may run into a host of problems that the 'one-off' was supposed to fix. This can be made worse if a new developer comes along, sees the problem with the generic, and decides he's going to fix it with his own one-off function.
So...
What are the options for working around this seemingly common issue?
I've looked at, and used UnitOfWork and right now that seems to be the only option that actually resolves the problem - but seems like attacking a fly with a sledgehammer.
You could do :
public bool Save<T>(T entity) where T : class
{ ... some storage logic ... }
public bool Save(SpecificClass entity)
{ ... special logic ... }
For example:
public class SpecificClass
{
}
public class Specializer
{
public bool GenericCalled;
public bool SpecializedCalled;
public bool Save<T>(T entity) where T : class
{
GenericCalled = true;
return true;
}
public bool Save(SpecificClass entity)
{
SpecializedCalled = true;
return true;
}
}
public class Tests
{
[Test]
public void TestSpecialization()
{
var x = new Specializer();
x.Save(new SpecificClass());
Assert.IsTrue(x.SpecializedCalled);
Assert.IsFalse(x.GenericCalled);
}
}
Well basicly C# does not allow template specialization, except through inheritence like this:
interface IFoo<T> { }
class Bar { }
class FooBar : IFoo<Bar> { }
At least it does not support this during compile time. However you can use RTTI to do what you are trying to achieve:
public bool Save<T>(T entity)
{
// Check if "entity" is of type "SpecificClass"
if (entity is SpecificClass)
{
// Entity can be safely casted to "SpecificClass"
return SaveSpecificClass((SpecificClass)entity);
}
// ... other cases ...
}
The is expression is pretty handy to do runtime type checks. It works similar to the following code:
if (entity.GetType() == typeof(SpecificClass))
// ...
EDIT : It is pretty common for unknown types to use the following pattern:
if (entity is Foo)
return DoSomethingWithFoo((Foo)entity);
else if (entity is Bar)
return DoSomethingWithBar((Bar)entity);
else
throw new NotSupportedException(
String.Format("\"{0}\" is not a supported type for this method.", entity.GetType()));
EDIT 2 : As the other answers suggest overloading the method with the SpecializedClass you need to take care if you are working with polymorphism. If you are using interfaces for your repository (which is actually a good way to design the repository pattern) there are cases where overloading would lead to cases in which you are the wrong method get's called, no matter if you are passing an object of SpecializedClass to the interface:
interface IRepository
{
bool Save<T>(T entity)
where T : class;
}
class FooRepository : IRepository
{
bool Save<T>(T entity)
{
}
bool Save(Foo entity)
{
}
}
This works if you directly call FooRepository.Save with an instance of Foo:
var repository = new FooRepository();
repository.Save(new Foo());
But this does not work if you are calling the interface (e.g. if you are using patterns to implement repository creation):
IRepository repository = GetRepository<FooRepository>();
repository.Save(new Foo()); // Attention! Call's FooRepository.Save<Foo>(Foo entity) instead of FooRepository.Save(Foo entity)!
Using RTTI there's only one Save method and you'll be fine.
Because function and operator overloads involving generics are bound at compile-time rather than run-time, if code has two methods:
public bool Save<T>(T entity) ...
public bool Save(SomeClass entity) ...
then code which tries to call Save(Foo) where Foo is a variable of some generic type will always call the former overload, even when the generic type happens to be SomeClass. My suggestion to resolve that would be to define a generic interface ISaver<in T> with a non-generic method DoSave(T param). Have the class that provides the Save method implement all of the appropriate generic interfaces for the types it can handle. Then have the object's Save<T> method try to cast this to an ISaver<T>. If the cast succeeds, use the resulting ISaver<T>; otherwise perform a generic save. Provided that the class type declaration lists all of the appropriate interfaces for the types it can save, this approach will dispatch Save calls to the proper methods.
Why using different names for your method?
See the following:
public class Entity
{
}
public class SpecificEntity : Entity
{
}
public class Program
{
public static void Save<T>(T entity)
where T : class
{
Console.WriteLine(entity.GetType().FullName);
}
public static void Save(SpecificEntity entity)
{
Console.WriteLine(entity.GetType().FullName);
}
private static void Main(string[] args)
{
Save(new Entity()); // ConsoleApplication13.Entity
Save(new SpecificEntity()); // ConsoleApplication13.SpecificEntity
Console.ReadKey();
}
}

Create Generic Class C#

I'm working on a repository for a list of entities, and I should repeat thea same class more than once, the only difference is type type .. is there a way to make it generic?
It should quite easy, for sure I don't know how to make this generic:
private Namespace.DAL.UserProfileRepository _rep = new Namespace.DAL.UserProfileRepository();
The class I'm repeating it this:
public class UserProfileRepository : IEntityRepository<IUserProfile>
{
private Namespace.DAL.UserProfileRepository _rep = new Namespace.DAL.UserProfileRepository();
public IUserProfile[] GetAll()
{
return _rep.GetAll();
}
public IUserProfile GetById(int id)
{
return _rep.GetById(id);
}
public IQueryable<IUserProfile> Query(Expression<Func<IUserProfile, bool>> filter)
{
return _rep.Query(filter);
}
}
#NickBray hit the nail on the head. Regardless of how different or similar the actual concrete repository implementations are the DAL class in your example should expose the repository instance via an interface.
Ideally the exposed interface would be declared something like this.
interface IUserProfileRepository : IEntityRepository<IUserProfile>
{
}
This way you could add custom IUserProfile methods as necessary. While the IEntityRepository interface would define the common methods Add, Update, Remove and various QueryXXX methods.
I hope this example helpful for you. If I correctly understood your question, you want to make generizable your repository based on the interface "IEntityRepository".
Try something like this:
public class UserProfileRepository<TUserProfile> : IEntityRepository<TUserProfile> where TUserProfile : IUserProfile
{
private Namespace.DAL.UserProfileRepository _rep = new Namespace.DAL.UserProfileRepository();
public TUserProfile[] GetAll()
{
return _rep.GetAll();
}
public TUserProfile GetById(int id)
{
return _rep.GetById(id);
}
public IQueryable<TUserProfile> Query(Expression<Func<TUserProfile, bool>> filter)
{
return _rep.Query(filter);
}
}

How to create instance of inherited in static base method?

From an instance, I might do this.
var obj= Activator.CreateInstance(GetType());
Not sure how to get typeof of the inherited class in a static base method though.
Is this the best way forward?
public static Method<T>() where T : SomeBase, new()
You could make the base class generic and close the generic in the derived class.
public abstract class CreatorOf<T> where T : CreatorOf<T>
{
public static T Create()
{
return (T)Activator.CreateInstance(typeof(T));
}
}
public class Inheritor : CreatorOf<Inheritor>
{
public Inheritor()
{
}
}
public class Client
{
public Client()
{
var obj = Inheritor.Create();
}
}
There are some who consider this to be an "anti-pattern", but I believe there are circumstances where it is an acceptable approach.
Maybe you should better tryto use abstract factory pattern?
http://en.wikipedia.org/wiki/Abstract_factory_pattern
There is no such thing as a derived static method. So there is no way to create a static factory method that returns a different type depending on which derived class you call it on.
As Lonli-Lokli suggested, you should use the Abstract Factory design pattern.
public interface ISomething
{
void DoSomething();
}
public class SomeClass : ISomething
{
public virtual void DoSomething() { Console.WriteLine("SomeClass"); }
}
public class SomeDerivedClass : SomeClass
{
private int parameter;
public SomeDerivedClass(int parameter)
{
this.parameter = parameter;
}
public virtual void DoSomething()
{
Console.WriteLine("SomeDerivedClass - {0}", parameter);
base.DoSomething();
}
}
public interface IFactory
{
public ISomething Create();
}
public class SomeClassFactory : IFactory
{
public ISomething Create() { return new SomeClass(); }
}
public class SomeDerivedClassFactory : IFactory
{
public ISomething Create() { return new SomeDerivedClass(SomeParam); }
public int SomeParam { get; set; }
}
Pros of Abstract Factory vs static Factory methods:
It is much more flexible, allowing a new implementation of your factory logic (which can be as complicated as you want) for every implementor of the abstract factory. You could have more than one factory per class, if you wanted.
Since you aren't calling a static method, it is much easier to replace at runtime. This is quite useful for injecting mocks in unit tests.
The pros are huge. Abstract Factories are superior to static factory methods in every way, even if you could get static methods to work the way you want them to.
Cons of Abstract Factory vs static Factory methods:
Users of the abstract factory must have a factory instance to create your derived types.
You have to write a new abstract factory implementation for each derived class.
The cons are very marginal.
It is extremely easy for a user to instantiate a factory to create a single object:
MyClass myClass = new MyClassFactory().Create();
As for code duplication in the factory implementation: Saving the implementer a tiny bit of typing is pointless. It is a goal in programming to write code that can be read, understood, and easily modified. There is no programming goal to save paper or keystrokes :)

Categories

Resources