Допустим, у меня есть библиотека классов, которая определяет пару интерфейсов сущностей:
public interface ISomeEntity { /* ... */ }
public interface ISomeOtherEntity { /* ... */ }
Эта библиотека также определяет интерфейс IRepository
:
public interface IRepository<TEntity> { /* ... */ }
И, наконец, библиотекаимеет абстрактный класс RepositorySourceBase
(см. ниже), который должен реализовать основной проект.Цель этого класса - позволить базовому классу захватывать новые Repository
объекты во время выполнения.Поскольку необходимы определенные репозитории (в этом примере репозиторий для ISomeEntity
и ISomeOtherEntity
), я пытаюсь написать общие перегрузки метода GetNew<TEntity>()
.
Следующая реализация не компилируется (второй метод GetNew()
помечается как "уже определенный", хотя предложение where отличается), но он добивается того, чего я пытаюсь достичь:
public abstract class RepositorySourceBase // This doesn't work!
{
public abstract Repository<TEntity> GetNew<TEntity>()
where TEntity : SomeEntity;
public abstract Repository<TEntity> GetNew<TEntity>()
where TEntity : SomeOtherEntity;
}
Предполагаемое использование этого класса будетбыть примерно таким:
public class RepositorySourceTester
{
public RepositorySourceTester(RepositorySourceBase repositorySource)
{
var someRepository = repositorySource.GetNew<ISomeEntity>();
var someOtherRepository = repositorySource.GetNew<ISomeOtherEntity>();
}
}
Между тем, в моем основном проекте (который ссылается на проект библиотеки) у меня есть реализации ISomeEntity
и ISomeOtherEntity
:
public class SomeEntity : ISomeEntity { /* ... */ }
public class SomeOtherEntity : ISomeOtherEntity { /* ... */ }
Основной проект также имеет реализацию для IRepository<TEntity>
:
public class Repository<TEntity> : IRepository<TEntity>
{
public Repository(string message) { }
}
И самое главное, он имеет реализацию абстрактного RepositorySourceBase
:
public class RepositorySource : RepositorySourceBase
{
public override IRepository<ISomeEntity> GetNew()
{
return new (IRepository<ISomeEntity>)Repository<SomeEntity>(
"stuff only I know");
}
public override IRepository<ISomeOtherEntity> GetNew()
{
return new (IRepository<ISomeEntity>)Repository<SomeOtherEntity>(
"other stuff only I know");
}
}
Так же, какс RepositorySourceBase
второй метод GetNew()
помечается как «уже определенный».
Итак, C # в основном думает, что я повторяю тот же метод, потому что нет никакого способа отличить методы от их параметолько , но если вы посмотрите на мой пример использования, мне кажется, что я смогу отличить, какой GetNew()
я хочу, от параметра универсального типа, например, <ISomeEntity>
или <ISomeOtherEntity>
).
Что мне нужно сделать, чтобы заставить это работать?
Обновление
В итоге я решил эту проблему с помощью специально названных методов и *Параметр 1055 *.
Итак, RepositorySourceBase
теперь выглядит так:
public abstract class RepositorySourceBase
{
public abstract Repository<ISomeEntity> GetNewSomeEntity();
public abstract Repository<ISomeOtherEntity> GetNewSomeOtherEntity();
}
И RepositorySource
выглядит так:
public class RepositorySource : RepositorySourceBase
{
public override IRepository<ISomeEntity> GetNewSomeEntity()
{
return new (IRepository<ISomeEntity>)Repository<SomeEntity>(
"stuff only I know");
}
public override IRepository<ISomeOtherEntity> GetNewSomeOtherEntity()
{
return new (IRepository<ISomeEntity>)Repository<SomeOtherEntity>(
"other stuff only I know");
}
}
Теперь, что началосьвсе это было связано с тем, что мне был нужен общий класс RepositoryUtilizer
, который мог бы получить репозиторий из источника, просто зная тип репозитория (который можно указать как параметр универсального типа).Оказывается, это было невозможно (или, по крайней мере, нелегко).Однако то, что возможно , это возможность использовать делегат Func<T, TResult>
в качестве параметра, чтобы класс RepositoryUtilizer
мог получить хранилище без необходимости «знать» имя метода.
Вотпример:
public class RepositoryUtilizer
{
public DoSomethingWithRepository<TEntity>(
Func<TRepositorySource, IRepository<TEntity>> repositoryGetter)
{
using (var repository = repositoryGetter(RepositorySource))
{
return repository.DoSomething();
}
}
}
}