Как объявить тип generi c вне объявления класса - PullRequest
0 голосов
/ 05 августа 2020

Я с успехом использую это обобщенное объявление типа c на протяжении всего тестового приложения

public class TestController<TSchool>
    where TSchool: IHasStudents, IHasTeachers, IHasAdmin, new()

Beacuse я создам несколько контроллеров, например TestController<University> или TestController<PrimarySchool>, и они отлично работают.

Однако повторный ввод <TSchool> where TSchool: IHasStudents, IHasTeachers, IHasAdmin, new() в каждом новом классе, который мне нужно использовать, становится очень повторяющимся TSchool

Я пробовал:

  1. public interface TSchool : IHasStudents, IHasTeachers, IHasAdmin, new()

Но компилятору не нравится синтаксис new()

public abstract class TSchool : IHasStudents, IHasTeachers, IHasAdmin, new()

Также безрезультатно.

Есть ли способ объявить тип generi c вне каждого объявления класса?

Ответы [ 2 ]

1 голос
/ 05 августа 2020

Общий тип c не является ни интерфейсом, ни абстрактным классом, это заполнитель, не имеющий никакого значения, кроме данного имени. Вот почему вам нужно указать C#, что именно реализует этот заполнитель, чтобы иметь возможность использовать его функции, по крайней мере те, которые открываются через интерфейсы и / или специальные вещи, такие как new().

У вас есть много других вариантов , например наследование. Вместо того, чтобы принимать общие типы c, вместо этого требуется базовый тип. object всегда доступен (хотя, если вы go до этого уровня, лень действительно победила ваш проект). dynamic - тоже выбор. И т.д. Возможно, внедрение зависимостей - это в первую очередь ответ на всю вашу проблему.

0 голосов
/ 06 августа 2020

Вы можете использовать вложенные классы

public class TestController<TSchool> where TSchool: IHasStudents, IHasTeachers, IHasAdmin, new()
{
    //don't need to re-declare TSchool, since TSchool is accessable in the nested classes
    public class TestA
    {

    }

    public class TestB
    {

    }
}

При этом вам нужно будет подумать о способе инициализации вложенных классов. Вот несколько идей.

using System;

namespace ConsoleApp1
{
    class Program
    {
        static void Main(string[] args)
        {
            //initialize controller
            var testController = new TestController<University>();

            //initialize Tests and pass the reference of the controller
            var testA_1 = new TestController<University>.TestA(testController);
            var testB_1 = new TestController<University>.TestB(testController);

            //initialize the Tests without a reference of the controller
            var testA_2 = new TestController<University>.TestA();
            var testB_2 = new TestController<University>.TestB();

            //use create methods, and maybe additionally hide the public constructors
            var testA_3 = testController.CreateTestA();
            var testB_3 = testController.CreateTestB();

            //use a static TestController class, and call the public constructors
            var testA_4 = new StaticTestController<University>.TestA();
            var testB_4 = new StaticTestController<University>.TestB();

            //use a static TestController class but hide the public constructors and use create methods 
            var testA_5 = StaticTestController<University>.CreateTestA();
            var testB_5 = StaticTestController<University>.CreateTestB();
        }
    }
}

public class TestController<TSchool> where TSchool : IHasStudents, IHasTeachers, IHasAdmin, new()
{
    private TSchool _school;

    public TestController()
    {
        _school = new TSchool();
    }
    public class TestA
    {
        public TestA()
        {

        }
        public TestA(TestController<TSchool> controller)
        {
            var school = new TSchool();
            var schoolController = controller._school;
        }
    }
    public class TestB
    {
        public TestB()
        {

        }
        public TestB(TestController<TSchool> controller)
        {
            var school = new TSchool();
            var schoolController = controller._school;
        }
    }
    public TestA CreateTestA()
    {
        return new TestA(this);
    }
    public TestB CreateTestB()
    {
        return new TestB(this);
    }
}
public static class StaticTestController<TSchool> where TSchool : IHasStudents, IHasTeachers, IHasAdmin, new()
{
    private static TSchool _school;

    static StaticTestController()
    {
        _school = new TSchool();
    }

    public class TestA
    {
        public TestA()
        {
            var school = new TSchool();
            var schoolController = _school;
        }
    }

    public class TestB
    {
        public TestB()
        {
            var school = new TSchool();
            var schoolController = _school;
        }
    }

    public static TestA CreateTestA()
    {
        return new TestA();
    }
    public static TestB CreateTestB()
    {
        return new TestB();
    }
}
public class School : IHasAdmin, IHasTeachers, IHasStudents
{

}
public class University : IHasAdmin, IHasTeachers, IHasStudents
{

}
public interface IHasStudents
{

}
public interface IHasTeachers
{

}
public interface IHasAdmin
{

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