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?

Was it helpful?

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>
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top