I have the following DBML modification (i'm using Linq to SQL as a DAL).
public interface ILinqSQLObject { }
// these are objects from SQL Server mapped into Linq to SQL
public partial class NEWDEBT : ILinqSQLObject { }
public partial class OLDDEBT : ILinqSQLObject { }
public partial class VIPDEBT : ILinqSQLObject { }
With that i can manipulate my Linq objects more properly on other areas.
I've just done an IRepository pattern implementation.
public interface IDebtManager<T>
{
IQueryable<T> GetAllDebts();
IQueryable T GetSpecificDebt(System.Linq.Expressions.Expression<Func<T, bool>> predicate);
void Insert(T debt);
// other methods
}
public class DebtManager<T> : IDebtManager<T> where T : class, ILinqSQLObject
{
DebtContext conn = new DebtContext();
protected System.Data.Linq.Table<T> table;
public DebtManager()
{
table = conn.GetTable<T>();
}
public void Insert(T debt)
{
throw new NotImplementedException();
}
public IQueryable<T> GetSpecificDebt(System.Linq.Expressions.Expression<Func<T, bool>> predicate)
{
return table.Where(predicate);
}
public IQueryable<T> GetAllDebts()
{
return table;
}
}
And that works flawlessly. But, there are sometimes that i don't know, on compilation time, which specific table i'll be using. For that i tried to create a simple generic factory for my DebtManager.
public static class DebtFactoryManager
{
public static DebtManager<ILinqSQLObject> GetDebtManager(string debtType)
{
switch (debtType)
{
case "New Client":
return new DebtManager<NEWDEBT>();
case "Old Client":
return new DebtManager<OLDDEBT>();
case "VIP Client":
return new DebtManager<VIPDEBT>();
default:
return new DebtManager<NEWDEBT>();
}
return null;
}
}
However it doesn't work. It says that i cannot 'implicity convert DebtManager<NEWDEBT> to DebtManager<ILinqSQLObject>', but if NEWDEBT implements ILinqSQLObject, why isn't the compiler recognizing it? Obviously i'm doing some mistake but i can't see it.
This error is caused by the fact that generics do not implicitly support covariance; that is, treating a specific generic parameter type as if it were one of its base types.
Couple ways around this. First, you can define a non-generic DebtManager base class that the generic DebtManager inherits from, and return that. Second, you can define a generic interface that DebtManager implements; generic interfaces CAN be defined to be covariant, by using the keyword out before the generic type parameter.
EDIT: Let's go back to the primary need. You may not know, at compile-time, what type of object you will be required to work with and therefore you don't know which Repository you need. Might I suggest, then, that instead of a Repository-per-table architecture, you use a Repository-per-database. DebtManager is already generic to any Linq to SQL type; why not then make the methods generic as well, allowing them to be generic from call to call?
public interface IRepository<T> where T:class, ILinqSqlObject
{
IQueryable<TSpec> GetAllDebts<TSpec>() where TSpec : T;
IQueryable<TSpec> GetSpecificDebt<TSpec>(System.Linq.Expressions.Expression<Func<TSpec, bool>> predicate) where TSpec : T;
void Insert<TSpec>(TSpec debt) where TSpec:T;
// other methods
}
interface IDebtObject : ILinqSqlObject
public interface IDebtManager:IRepository<IDebtObject> { }
public class DebtManager:IDebtManager
{
DebtContext conn = new DebtContext();
public DebtManager()
{
}
public void Insert<T>(T debt) where T:IDebtObject
{
throw new NotImplementedException();
}
public IQueryable<T> GetSpecificDebt(System.Linq.Expressions.Expression<Func<T, bool>> predicate) where T:IDebtObject
{
return conn.GetTable<T>().Where(predicate);
}
public IQueryable<T> GetAllDebts<T>() where T:IDebtObject
{
return conn.GetTable<T>();
}
}
Related
I've defined a "type translator" interface (please don't mention AutoMapper, not relevant) as follows:
public interface ITranslator<TSource, TResult>
{
TResult Translate(TSource source);
}
And for convenience sake, I've defined an extension method for enumerables:
public static class ExtendITranslator
{
public static IEnumerable<TResult> TranslateSet<TSource, TResult>(
this ITranslator<TSource, TResult> self,
IEnumerable<TSource> sourceSet)
{
return sourceSet.Select(o => self.Translate(o));
}
}
And then I define the implementation as so:
public class Translator :
ITranslator<Report, Report.ReportServiceModel>,
ITranslator<Report.ReportServiceModel, Report>
{
public Report Translate(Report.ReportServiceModel source)
{
throw new NotImplementedException();
}
public Report.ReportServiceModel Translate(Report source)
{
throw new NotImplementedException();
}
}
The problem is, when I work with the Translator implementation, it doesn't expose TranslateSet as an extension method, unless I cast:
Translator translator = new Translator();
// not exposed
translator.TranslateSet(/* ... */);
// exposed with a cast
(translator as ITranslator<Report, Report.ReportServiceModel>).TranslateSet(/* ... */);
Why is this? Other class implementations expose extension methods defined for the interfaces they implement:
public interface IUpdater<TModel> where TModel : class, new()
{
bool Update(TModel model);
}
public static class ExtendIRepositoryWriter
{
public static int UpdateSet<TModel>(
this IRepositoryWriter<TModel> self,
IEnumerable<TModel> modelSet) where TModel : class, new()
{
return modelSet.Count(o => self.Update(o));
}
}
public class ReportUpdater : IUpdater<Report>
{
public bool Update(Report model)
{
throw new NotImplementedException();
}
}
In this case, the UpdateSet extension method is available on instances of ReportUpdater:
ReportUpdater reportUpdater = new ReportUpdater();
// all good!
reportUpdater.UpdateSet(/* ... */);
Can anyone shed some light on this? Did I fat-finger a typo or something? (It is Friday night after all)
Your other working example is actually misleading and is not a true apples-to-apples comparison.
Due to a single generic argument, the compiler is able to infer the type since you are invoking on an instance of that type.
This is not the case with the extension giving you trouble, since there are two type arguments. You can resolve this by assigning the concrete type to an interface declaring the types.
ITranslator<Report, Report.ReportServiceModel> translator = new Translator();
translator.TranslateSet(/* ... */);
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>();
I have a repository class with some generic methods. One is
public IEnumerable<T> FindAll<T>(Expression<Func<T, bool>> predicate) where T : class
{
return GetDbSet<T>().Where(predicate);
}
For unit testing I have a TestRepository which uses in-memory objects instead of a database. The TestRepository overrides the FindAll method and I want to control what is returned. So I want to be able to do something like this:
public override IEnumerable<T> FindAll<T>(Expression<Func<T, bool>> predicate)
{
return MyEntities.Where(predicate).Cast<T>();
}
But MyEntities.Where() only accepts a Expression<Func<MyEntity, bool>>.
How can I cast/convert the generic expression to the strongly typed expression?
You can do something like this. Not sure whether it's a good idea, but it works. Basically, your overload can compare the type parameter T to your entity class. If the predicate has the right type, you can cast. Otherwise, you don't have anything to return.
public class MyEntity { public int x; }
MyEntity[] MyEntitiesList = Enumerable.Range(1,5).Select(y => new MyEntity() { x = y }).ToArray();
public IEnumerable<T> FindAll<T>(Expression<Func<T, bool>> predicate)
{
if (typeof(T) == typeof(MyEntity))
{
return (IEnumerable<T>)MyEntitiesList.Where((predicate as Expression<Func<MyEntity, bool>>).Compile());
}
return new T[0];
}
Usage:
var res = FindAll((MyEntity y) => y.x % 2 == 0).ToList();
Console.WriteLine(res.Count);
It looks like your repository implementation has a major flaw in a sense that the caller is not aware that he can only pass arguments of certain types (e.g. it looks like I can do FindAll<int>(v => v > 0) but in fact, the underlying implementation only works with MyEntity). In other words, it's trying to be too "smart", it's not intuitive and error-prone.
One way of fixing this can be by introducing an interface/base class:
public interface IRepository<T>
{
IEnumerable<T> FindAll<T>(Expression<Func<T, bool>> predicate);
}
// A base class that can carry helper functionality.
public abstract class Repository<T> : IRepository<T>
{
private readonly IEnumerable<T> _entities;
protected Repository(IEnumerable<T> entities)
{
_entities = entities;
}
public IEnumerable<T> FindAll(Expression<Func<T, bool>> predicate)
{
return _entities.Where(predicate);
}
}
// Concrete implementation
public class MyEntityRepository : Repository<MyEntity>
{
public MyEntityRepository() : base(new MyDbContext().MyEntities) { }
}
In the above example I'm referring to MyDbContext just for demonstration purposes (so it looks a bit more familiar if you worked with Entity Framework).
Now you can instantiate MyEntityRepository and use it throughout the application. In case you're using some sort of IoC, you can modify the code slightly:
public interface IMyEntityRepository : IRepository<MyEntity>
{
// ...
}
public class MyEntityRepository : Repository<MyEntity>, IMyEntityRepository
{
// ...
}
And now you can easily inject and mock IMyEntityRepository within your application.
Hope this helps.
UPDATE
As it turns out, since the given implementation is used for testing purposes only, you could try producing the expression of a desired type the following way:
return MyEntities.Where(Expression.Lambda<Func<MyEntity, bool>>(predicate.Body,
predicate.Parameters)).Cast<T>();
You can also apply some casting to the lambda parameter, if explicit one is needed.
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);
}
}
I have almost completed implementing my repository pattern by having a IRepository<T> interface, a NewsRepository class and a News entity. The problem I ran into was trying to abstract out common methods to a base Repository class.
I could not find a way to abstract the Get method in the NewsRepository as it contains a specific Linq expression.
My questions are:
1) How do I abstract to a base class the public T Get(int id) method please? The only way I have done it so far is by passing in Expression<Func<T,bool>> instead of an int, but then that deosn't really abstract out common behaviour as each sub-class will still need to pass in an expression that is almost identical in each case ie n => n.id == id.
2) How do I pass into the base class on the Update method the sub-class GetViolations and map methods please? I imagine the solution is possibly by using delegates, but I couldn't get the syntax to compile
This is a simplified set of the code - in practice I have a Save method which does Update and Insert rather than just the Update shown here.
public interface IRepository<T>
{
T Get(int id);
void Update(T item);
}
public class NewsRepository : IRepository<News>
{
private Table<News> _newsTable;
public NewsRepository(string connectionString)
{
_newsTable = new DataContext(connectionString).GetTable<News>();
}
public News Get(int id)
{
return _newsTable.SingleOrDefault(n => n.NewsId == id);
}
public void Update(News item)
{
var errors = item.GetRuleViolations();
if (errors.Count > 0)
throw new RuleException(errors);
News dbNews = _newsTable.SingleOrDefault(n => n.NewsId == item.NewsId);
map(dbNews, item);
_newsTable.Context.SubmitChanges();
}
private void map(News dbNews, News news)
{
dbNews.Title = news.Title;
dbNews.Article = news.Article;
}
}
public class Repository<T> where T : class
{
protected Table<T> _table;
public Repository(Table<T> t)
{
_table = t;
}
//How do i do this??! - This doesn't compile due to T no having a NewsId
public T Get(int id)
{
return _table.SingleOrDefault(n => n.NewsId == id);
}
//This seems to be a solution, but it's not really abstracting common behaviour as each
//sub-class will still need to pass in the same linq expression...
public T Get(Expression<Func<T,bool>> ex)
{
return _table.SingleOrDefault(ex);
}
public void Update(T item)
{
//How is it possible to pass in the GetRuleViolations and map functions to this method?
var errors = item.GetRuleViolations();
if (errors.Count > 0)
throw new RuleException(errors);
T dbNews = _table.SingleOrDefault(n => n.NewsId == item.NewsId);
map(dbNews, item);
_table.Context.SubmitChanges();
}
}
L2S supports neither layer supertypes nor using interface members in queries, which makes reuse quite difficult. One option is to dynamically build an expression tree. It's a bit messy, but if you isolate it to your base class repository it's not that bad.
Here is an example:
public interface IEntity
{
int Id { get; }
}
public partial class News : IEntity
{
}
public class Repository<T> where T : class, IEntity
{
private readonly DataContext _db;
public Repository(DataContext db)
{
_db = db;
}
public T Get(int id)
{
Expression<Func<T, bool>> hasId = HasId(id);
return _db.GetTable<T>().Single(hasId);
}
// entity => entity.Id == id;
private Expression<Func<T, bool>> HasId(int id)
{
ParameterExpression entityParameter = Expression.Parameter(typeof (T), "entity");
return Expression.Lambda<Func<T, bool>>(
Expression.Equal(
Expression.Property(entityParameter, "Id"),
Expression.Constant(id)
),
new[] {entityParameter}
);
}
}
See also http://msdn.microsoft.com/en-us/library/bb397951.aspx
It really helps to have a layer supertype for entities. They will share an Id property. You won't have to deal with an expression to represent the id proeprty, you'll just know what it is.
The template method pattern. In this pattern your base Update does all the work calling helper methods in order, and your derived classes implement those protected abstract helper methods.