2011-01-06 69 views
1

可以说我有以下的阶层结构在我的数据访问层:如何避免ref参数不允许类型变化?

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) 
    } 
    } 
} 

这让我有我的模型可以实现处理这些接口的各种接口,可重复使用的行为:

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

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

经理会很乐意接受这些,因为在IBehavior<T>中存在矛盾。

class MyModel : IUnique, ITimestampable { ... } 

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

超。

但是现在,我想让每个行为都对实体应用一组LINQ过滤器。我的第一个想法是将这个方法添加到IBehavior<T>

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

...其中一个执行行为将应用一组Where条款在其自由裁量权的枚举。

但是,事实证明,ref parameters don't allow type variation。我努力寻找一种方法来实现这种功能,同时保持类型安全和接口的逆变性质。任何想法都表示赞赏。

+1

我期望`ApplyFilters`有签名`IEnumerable ApplyFilters(IEnumerable models)' – Gabe 2011-01-06 14:29:31

+0

也不管用,它使T成为返回类型。我记得都尝试过,在我的用例中使用ref更有意义。这样,如果行为不想应用任何过滤器,则可以将该方法留空。 – 2011-01-06 14:38:11

回答

1

不知道这是否会在您的确切上下文中工作,但您是否尝试过使ApplyFolders泛型本身?

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

这太疯狂了,它的工作原理!谢谢,我自己也不会想到这件事。 – 2011-01-06 15:58:49

1

我会看看Ptr class。最近我一直在利用这个类来彻底地破解.NET放入ref关键字的所有限制,让我对CLR出于某种原因感觉我没有权利使用副作用对象。