Generic enforcement
-
19-08-2019 - |
Question
I have a generic class
public MyClass<TContext, T> where TContext : DataContext
that effectively acts on an instance of another
public class MyOtherClass<T> : IEnumerable<T>
I want to enforce that the TContext
has a Table<T>
. Is there a clean way to enforce this?
Solution
Are you wanting to verify that TContext has a member which is a Table<T>? If so, the only way to do that is to define an interface for this contract and alter your generic constraints
interface IMyTable<T> {
Table<T> Table;
}
public MyClass<TContext,T> where TContext : DataContext,IMyTable<T>
EDIT
Jason posted a clarifying comment to my answer. The name Table is not static, it instead depends on the type of T.
If that's the case then there is no way to statically enforce this through generic constraints. The best you could do is create an adapter class which implements IMyTable<> and provides a DataContext and a Table instance.
interface IMyTable2<T> {
DataContext DataContext {get; }
Table<T> Table {get; }
}
class MyAdapter: IMyTable2<T> {
private MyOtherClass<T> _other;
public DataContext DataContext { get { return _other.DataContext } }
public Table<T> Table { get { return _other.TableWithDifferentName; } }
}
OTHER TIPS
I think JaredPar had the right idea the first time around.
interface IMyTable<T>
{
Table<T> TheTable {get;}
}
public class MyClass<TContext,T> where
TContext : DataContext,IMyTable<T>
{
//silly implementation provided to support the later example:
public TContext Source {get;set;}
public List<T> GetThem()
{
IMyTable<T> x = Source as IMyTable<T>;
return x.TheTable.ToList();
}
}
I want to extend his thought by adding an explicit interface implementation. This addresses Jason's remark about accessing the table property through IMyTable. The type must be involved somehow, and if you have an IMyTable<T>
, the type is involved.
public partial class MyDataContext:IMyTable<Customer>, IMyTable<Order>
{
Table<Customer> IMyTable<Customer>.TheTable
{ get{ return this.GetTable<Customer>(); } }
Table<Order> IMyTable<Order>.TheTable
{ get{ return this.GetTable<Order>(); } }
}
Now it is possible to do this:
var z = new MyClass<MyDataContext, Customer>();
z.Source = new MyDataContext();
List<Customer> result = z.GetThem();
the only way to enforce it is if Table was in an interface, and you assigned a generic constraint ... so something like
public class MyOtherClass<T> : IEnumerable<T>, IHasTable<T>