C #: родовое ограничение метода для подклассов - PullRequest
0 голосов
/ 30 мая 2018

У меня есть два вида базовых классов:

public class Parent { }
public abstract class Child : Parent 
{
    string ChildKey { get; set; }
}

Производные от родителей, есть много детей:

public class Kid1 : Parent { public string Name { get; set; } }
public class Kid2 : Parent { public long Number { get; set; } }
...

, а также много детей как особая группа детей с дополнительнымиproperties:

public class Child1 : Child { public string Street { get; set; } }
public class Child2 : Child { public long Account { get; set; }}

Теперь у меня есть два универсальных класса репозитория, где «Special One» более специфично воздействует на дополнительные свойства, используя дополнительный фильтр:

public class Repository<T> : IRepository<T> where T : Parent 
{ 
    public IEnumerable<T> GetAll() { return something; }
}
public class ChildRepository<T> : Repository<T>, IChildrenRepository<T> where T : Child 
{ 
    public override IEnumerable<T> GetAll() { return base.GetAll().Where(x => x.ChildKey == "y"); }
}

с интерфейсами:

public interface IRepository<T> where T : Parent
{ IEnumerable<T> GetAll(); }
public interface IChildRepository<T> : IRepository<T> where T : Child { }

Мне также нужна безопасность типов GetAll () - результаты.

Теперь мне нужен универсальный метод для создания желаемого хранилища:

IRepository<T> GetRepository() where T : WhatConstraint
{
    if (typeof(Child).IsAssignableFrom(T))
        return new ChildRepository<T>();    // return 1
    return new Repository<T>();             // return 2
}

Какое правильное ограничение?для return 1 требуется Child-Constraint (что неверно для return 2), говоря, что тип T нельзя использовать в качестве параметра типа в методе, поскольку не существует неявного преобразования ссылок из T в Child.

T: Child-ограничение является более точным в ChildRepository (и, следовательно, полезно, так как я могу полагаться на некоторые свойства).Если я использую одно и то же T: Parent-ограничение репозитория, я должен проверить тип, всегда ли T наследуется от Child ...

Есть ли какие-нибудь решения для этого?

1 Ответ

0 голосов
/ 04 июня 2018

Хорошо, вот подробное решение (которое может быть написано как более коротким, так и менее читаемым).Так как Repository и ChildRepository имеют противоречивые ограничения (что хорошо для репозиториев, но плохо для GetRepository-factory), я не могу создать ChildRepository, используя new-keyword.Я должен создать этот объект с помощью CreateInstance.

IRepository<T> GetRepository() where T : Parent
{
    if (typeof(Child).IsAssignableFrom(T))
    {
        Type childType = typeof(T);  // which is both, Parent and Child
        Type classType = typeof(ChildRepository<>);
        Type[] typeParams = { childType };
        Type repositoryType = classType.MakeGenericType(typeParams);
        return Activator.CreateInstance(resultType) as IRepository<T>;
    }
    return new Repository<T>();
}

Недостаток этого решения: более сложный анализ кода, неясная обнуляемость результата, не очень интуитивно читаемый (особенно существующие ограничения).Но это работает.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...