Question

Lets say I have the following class structure in my data access layer:

interface IBehavior<in T>
{
  void Load(T model);
}

class ModelManager<T>
{
  ModelManager(IEnumerable<IBehavior<T>> behaviors) { ... }

  void Load(T model)
  {
    foreach (var behavior in behaviors) {
      behavior.Load(model)
    }
  }
}

This lets me have various interfaces that my models can implement, and reusable behaviors that handle those interfaces:

interface IUnique { ... }
class UniqueBehavior : IBehavior<IUnique>  { ... }

interface ITimestampable  { ... }
class TimestampableBehavior : IBehavior<ITimestampable> { ... }

And the manager will gladly take these because of contravariance in IBehavior<T>.

class MyModel : IUnique, ITimestampable { ... }

new ModelManager<MyModel>(new IBehavior<MyModel>[] {
  new UniqueBehavior(),
  new TimestampableBehavior()
});

Super.

But now, I want to let each behavior apply a set of LINQ filters to the entity too. My first idea was to add this method to IBehavior<T>:

void ApplyFilters<IEnumerable>(ref IEnumerable<T> models)

... in which an implementing behavior would apply a set of Where clauses to the enumeration at its discretion.

However, as it turns out, ref parameters don't allow type variation. I'm struggling to find a way to implement this kind of functionality while maintaining both type safety and the contravariant nature of the interface. Any ideas are appreciated.

Was it helpful?

Solution

Not sure if this would work in your exact context, but have you tried making ApplyFolders generic itself?

void ApplyFolders<TEnum>(ref IEnumerable<TEnum> models) where TEnum : T;

OTHER TIPS

I would take a look at the Ptr class. I've been taking advantage of this class recently to completely bust all of the limitations .NET puts on ref keywords to let me side effect objects the CLR for some reason feels I have no right to.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top