Вы можете сделать это, определив интерфейс через A и B.
public interface IHasName // contrived, I know
{
string Name {get;}
}
Классы LINQ-To-SQL являются частичными, поэтому в вашей части определения частичного класса вы можете добавить интерфейс, напримерИтак:
public partial class A : IHasName {}
public partial class B : IHasName {}
Как видите, реализация не требуется, поскольку свойство Name реализовано в сгенерированной части Linq-To-Sql.
Теперь ограничьте ваш предикат типами, реализующимиИнтерфейс IHasName, и все готово:
private Expression<Func<T, bool>> FilterPredicate(string name) where T : IHasName
{
return x => x.Name == name;
}
теперь вы даже сможете определить метод расширения для IQueryable следующим образом:
public static T GetByName<T>(this IQueryable<T> queryable,
string name) where T : IHasName
{
return queryable.Where(FilterPredicate(name)).SingleOrDefault();
}
Небольшое предостережение: конечно,свойство в интерфейсе («Имя») должно точно соответствовать имени свойства в реализующих классах.Предположим, у вас есть класс C со свойством «MyName».Вы можете испытать желание реализовать интерфейс IHasName следующим образом:
public partial class C : IHasName
{
public string Name {return MyName;}
}
Это, конечно, не будет работать, так как синтаксический анализатор выражений Linq-To-Sql будет использовать «Name» вместо фактического свойства «MyName»поэтому он не сможет сопоставить это выражение с допустимым SQL.