문제

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.

도움이 되었습니까?

해결책

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;

다른 팁

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.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top