2011-01-06 3 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() 
}); 

Super.

Но теперь я хочу, чтобы каждое поведение применяло набор 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

+0

Не получилось бы, это делает T тип возврата. Я помню, как пытались оба, и в моем случае использования, использующем ref, имеет смысл. Таким образом, если поведение не хочет применять какие-либо фильтры, оно может просто оставить метод пустым. –

ответ

1

Не уверен, что это сработает в вашем конкретном контексте, но попробовали ли вы сделать сам ApplyFolders?

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

Это так безумно, что он работает! Спасибо, я бы не подумал об этом сам. –

+0

Это трюк, который я использую, когда не могу использовать дисперсию общего вида .NET 4. – thecoop

+0

Возможно, вы * не * хотите параметр 'ref'. – Gabe

1

Я хотел бы посмотреть на Ptr class. Я недавно воспользовался этим классом, чтобы полностью разрушить все ограничения. NET ставит ключевые слова ref, чтобы позволить мне объекты побочных эффектов. По какой-то причине CLR чувствует, что я не имею права.

+0

Это классный класс, но в этом случае он не сработает, потому что он не обошел проблему контравариантности - свойство было бы как внутри, так и снаружи. –

+0

Ограничения на 'ref' существуют для поддержания безопасности и проверяемости типа; имейте в виду, что 'ref' означает, что действительная« внешняя »переменная изменена, а не копия, и вы не хотите, чтобы экземпляр был изменен на что-то еще другим потоком под вами ... – thecoop

+0

@LLia и @thecoop с использованием PTR класс, давайте у вас есть использование ссылок, чтобы вы могли изменить базовую переменную, не используя ключевое слово ref. Этот класс действительно работает. Я использую это, чтобы использовать ref в методе возврата доходности. Методы с возвратом доходности не позволяют использовать переменные ref. –

 Смежные вопросы

  • Нет связанных вопросов^_^