Reputation:
In C# I have a generic class that looks like this:
public class DataManager<T> : IDisposable where T : class
That is used like this:
public T GetById(String id)
{
return this.Context.Set<T>().Find(id);
}
This works great.
However if I have 2 types in a manager, in this case, Ticket and TicketResponse, I would like to be able to override the type without having to add the type into every method call. Something like this:
public T GetById<T>(String id) where T : class
{
return this.Context.Set<T>().Find(id);
}
Where I can call it interchangeably like so:
var ticket = GetById(myId);
var ticketResponse = GetById<TicketResponse>(myId); // this would override
The idea is to not have to create a separate manager for a sub-object, but also to not have to get the entire ticket to have to iterate through the responses, but just be able to get it directly.
Is this possible?
Upvotes: 0
Views: 416
Reputation: 172330
You could use a wrapper that encapsulates two DataManagers:
class DataAndResponseManager<TData, TResponse>
{
private dataManager = new DataManager<TData>();
private responseManager = new DataManager<TResponse>();
public TData GetById(String id) { dataManager.GetById(id); }
public TResponse GetResponseById(String id) { responseManager.GetById(id); }
}
Advantage: Reuse of all existing DataManager code.
Disadvantage: Proxy methods required.
Upvotes: 0
Reputation: 6684
You could try something like this:
public T GetById( String id )
{
return GetById<T>( id );
}
public U GetById<U>( String id ) where U : T
{
return this.Context.Set<U>().Find( id );
}
So you have your original method but also an additional generic method which can take another parameter type that derives from T
.
Upvotes: 1
Reputation: 144136
Since the Context.Set
allows you to specify any T
you want, you could add an interface for the DataManager
class, add a base class which exposes a method on the underlying context and then implement the interface explicitly on your manager class:
public interface IDataManager<T> : IDisposable where T : class
{
T GetById(string id);
}
public class DataManagerBase : IDisposable
{
protected Find<T>(string id) where T : class
{
return this.Context.Set<T>().Find(id);
}
}
public class TicketManager : DataManagerBase, IDataManager<TicketResponse>, IDataManager<Ticket>
{
TicketResponse IDataManager<TicketResponse>.GetById(string id)
{
return this.Find<TicketResponse>(id);
}
Ticket IDataManager<Ticket>.GetById(string id)
{
return this.Find<TicketResponse>(id);
}
}
Upvotes: 2
Reputation: 172330
If I understood you correctly, Ticket
is a special case: Ticket
's DataManager should also provide methods for TicketResponse
. Is that correct?
In that case, you can just subclass DataManager<T>
and add the required functionality:
class TicketManager : DataManager<Ticket>
{
public TicketResponse GetResponseById(String id)
{
return this.Context.Set<TicketResponse>().Find(id);
}
}
which can be used as follows:
var ticket = myTicketManager.GetById(myId);
var ticketResponse = myTicketManager.GetResponseById(myId);
(If you are worried about the duplication of the GetById
code, just extract it into a static protected GetByIdInternal<TData>
method.)
Upvotes: 0