Вывод параметра типа в метод - PullRequest
3 голосов
/ 02 июля 2019

В моей библиотеке C # есть иерархия классов, представляющих доменные сущности, все они в конечном итоге происходят от корневого абстрактного класса с именем DomainEntity.Некоторые примеры Package или Customer.Я использую фабричные методы Create() в каждом классе для создания экземпляров.У меня также есть универсальный класс процессора Processor<T>, где T: DomainEntity.Этот класс процессора также использует фабричный метод для создания экземпляра и выполняет бизнес-логику, которая зависит от конкретного класса, следовательно, его параметра типа.Используя эту библиотеку, я могу, например, написать такой код:

var pkg = Package.Create(/* various arguments */);
var pro = Processor<Package>.Create(pkg);
pro.DoStuff();

Пока все хорошо.Теперь я хотел бы написать метод в DomainEntity, который возвращает процессор для любой конкретной сущности домена.Примерно так:

public Processor<T> CreateProcessor<T>()
    where T: DomainEntity
{
    var pro = Processor<T>.Create((T)this);
    return pro;
}

Этот метод можно использовать следующим образом:

var pkg = Package.Create(/* various arguments */);
var pro = pkg.CreateProcessor<Package>();
pro.DoStuff();

Это работает нормально, но я нахожу ссылку Package в вызове CreateProcessor() aбит избыточен, так как я вызываю метод в экземпляре Package, и поэтому нет никакой двусмысленности относительно того, к какому классу должен ссылаться параметр типа.Однако, это не скомпилируется:

var pkg = new Package(/* various arguments */);
var pro = pkg.CreateProcessor(); //<-- this does not compile.
pro.DoStuff();

Мой вопрос:

Есть ли альтернативный способ написания метода CreateProcessor(), так что параметр типа выводится компилятором изобъект это вызывается?

Я могу предоставить полный рабочий проект Visual Studio по запросу.

Ответы [ 2 ]

6 голосов
/ 02 июля 2019

Вам просто нужно создать универсальный метод расширения:

public static class EntityExtensions
{
    public static Processor<T> CreateProcessor<T>(this T entity)
        where T : DomainEntity
        => new Processor<T>(entity);
}

Это позволит вам использовать вывод типа просто отлично:

var package = new Package();
var processor = package.CreateProcessor();

Эта вторая строка эквивалентна:

var processor = EntityExtensions.CreateProcessor<Package>(package);
0 голосов
/ 02 июля 2019

Как насчет использования фабричного метода:

static Processor<T> CreateProcessor<T>() {
    var package = new Package();
    T pro = package.CreateProcessor<T>();
    return pro;
}

// Usage
CreateProcessor<Package>().DoStuff();

Я пытался найти способ использовать тихую специализацию типов некоторое время назад и понял, что это не работает в C #.Вы можете проверить это сообщение в блоге

...