Como posso contornar os parâmetros de referência que não permitem variação de tipo?
-
26-09-2019 - |
Pergunta
Digamos que eu tenha a seguinte estrutura de classes na minha camada de acesso a dados:
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)
}
}
}
Isso me permite ter várias interfaces que meus modelos podem implementar e comportamentos reutilizáveis que lidam com essas interfaces:
interface IUnique { ... }
class UniqueBehavior : IBehavior<IUnique> { ... }
interface ITimestampable { ... }
class TimestampableBehavior : IBehavior<ITimestampable> { ... }
E o gerente aceitará isso com prazer por causa da contravariância em IBehavior<T>
.
class MyModel : IUnique, ITimestampable { ... }
new ModelManager<MyModel>(new IBehavior<MyModel>[] {
new UniqueBehavior(),
new TimestampableBehavior()
});
Super.
Mas agora quero permitir que cada comportamento aplique um conjunto de filtros LINQ à entidade também.Minha primeira ideia foi adicionar esse método ao IBehavior<T>
:
void ApplyFilters<IEnumerable>(ref IEnumerable<T> models)
...em que um comportamento de implementação aplicaria um conjunto de Where
cláusulas à enumeração a seu critério.
No entanto, como se constata, parâmetros ref não permitem variação de tipo.Estou lutando para encontrar uma maneira de implementar esse tipo de funcionalidade, mantendo a segurança do tipo e a natureza contravariante da interface.Todas as ideias são apreciadas.
Solução
Não tenho certeza se isso funcionaria no seu contexto exato, mas você já tentou tornar o ApplyFolders genérico?
void ApplyFolders<TEnum>(ref IEnumerable<TEnum> models) where TEnum : T;
Outras dicas
eu daria uma olhada no Classe Ptr.Tenho aproveitado essa classe recentemente para eliminar completamente todas as limitações que o .NET impõe às palavras-chave ref para permitir que eu tenha efeitos colaterais que o CLR, por algum motivo, acha que não tenho o direito de fazer.