Тип нельзя использовать в качестве параметра типа в универсальном типе или методе

Я пишу свое первое приложение с использованием минимальных API в приложении .NET 8. Я выполняю обучающее упражнение, которое нашел в Microsoft Learn, и использую разработанную мной базу данных. Я столкнулся с этой ошибкой:

CS0311 Тип «Show1» нельзя использовать в качестве параметра типа. «TImplementation» в универсальном типе или методе 'ServiceCollectionServiceExtensions.AddScoped<TService, TImplementation>(IServiceCollection)». Нет неявной ссылки преобразование из «Show1» в «BlazorMediaLibrary.API.Interfaces.IShow1»

Я искал эту ошибку и придумал Почему ограничение общего типа приводит к ошибке неявного преобразования ссылок? здесь, на ТАК. Однако я не думаю, что это соответствует моей ситуации. Вот что я получил для своего интерфейса, который был сгенерирован, когда я формировал базу данных для создания классов модели и DbContext:

public interface IShow1
{
    int ShowId { get; set; }
    int ShowCode { get; set; }
    string EpisodeName { get; set; }
    string? Synopsis { get; set; }
    DateTime? DateLastViewed { get; set; }
    DateTime? OriginalBroadcastDate { get; set; }
    TimeOnly? PlayTime { get; set; }
    double? Rating { get; set; }

    TypeOfShow1 ShowCodeNavigation { get; set; }
    ICollection<Entries2> Entries2s { get; set; }
    ICollection<UserRating> UserRatings { get; set; }
}

и вот реализация класса модели:

public partial class Show1 : IShow1
{
    public int ShowId { get; set; }

    public int ShowCode { get; set; }

    public string EpisodeName { get; set; } = null!;

    public string? Synopsis { get; set; }

    public DateTime? DateLastViewed { get; set; }

    public DateTime? OriginalBroadcastDate { get; set; }

    public TimeOnly? PlayTime { get; set; }

    public double? Rating { get; set; }

    public virtual TypeOfShow1 ShowCodeNavigation { get; set; } = null!;
    public virtual ICollection<Entries2> Entries2s { get; set; } = new List<Entries2>();
    public virtual ICollection<UserRating> UserRatings { get; set; } = new List<UserRating>();
}

В файле Program.cs я определил эту запись:

internal record Show1(int ShowId, int ShowCode, string EpisodeName,
                      string? Synopsis, DateTime? DateLastViewed, 
                      DateTime? OriginalBoardcastDate, TimeOnly? PlayTime, float? Rating);

А вот строка в Program.cs, которая вызывает ошибку:

builder.Services.AddScoped<IShow1, Show1>();

Я не включил ShowCodeNavigation, Entries2 или UserRatings в определение записи в Program.cs.

Это причина моей проблемы?

Вы абсолютно уверены, что интерфейс IShow1, реализуемый вашим классом, тот же самый, который вы пытаетесь использовать, т. е. BlazorMediaLibrary.API.Interfaces.IShow1? Если вы поместите курсор в IShow1 в объявлении класса (где вы заявляете, что реализуете его) и нажмете F12, к какому интерфейсу он перейдет?

Jon Skeet 03.08.2024 16:50

Когда я навожу указатель мыши на IShow1 в классе Show1 в папке «Модели», он указывает на интерфейс в BlazorMediaLibrary.API.Interfaces. В файле Program.cs интерфейс IShow1, используемый в builder.Services.AddScoped(), также указывает интерфейс в BlazorMediaLibrary.API.Interfaces. А класс Show1 в том же builderr.Services.AddScoped() указывает на класс Show1 в папке Models.

Rod 04.08.2024 04:04

Ради ухмылки и смеха я решил закомментировать два оператора using в верхней части файла Program.cs, а затем заменил builder.Services.AddScoped на это: builder.Services.AddScoped<BlazorMediaLibrary.API.Interfaces‌​ .IShow1, BlazorMediaLibrary.API.Models.Show1>(); Это устранило ошибки. Я не понимаю, почему это устранило ошибки.

Rod 04.08.2024 04:10

Я пропустил, что вы также определили запись под названием Show1. Я сильно подозреваю, что проблема была в этом — обратите внимание, что в сообщении об ошибке речь идет не о BlazorMediaLibrary.API.Models.Show1, а только о Show1. Помимо всего прочего, наличие и класса, и записи с именем Show1 могло бы сбить с толку любого человека, работающего с кодом...

Jon Skeet 04.08.2024 08:39
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
1
4
53
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

В файле Program.cs я определил такую ​​запись: internal record Show1 ...

Он будет «затенять» Show1, который реализует интерфейс, и «импортируется» через соответствующий оператор using. Я бы порекомендовал переименовать record во что-нибудь другое, но если есть очень веская причина иметь как внутреннюю запись, так и класс с одним и тем же именем (я не могу придумать ни одного, но все же), вы можете использовать «полный» тип. имя для регистрации:

builder.Services.AddScoped<IShow1, BlazorMediaLibrary.API.Models.Show1>();

Если запись не используется в коде оператора верхнего уровня (т. е. в Program.cs), вы можете переключиться на «явный» метод Main (см. Должны ли директивы using находиться внутри или снаружи пространства имен в C#? для возможного объяснения):

namespace MyNamespace
{
    using BlazorMediaLibrary.API.Models; // moving import out of the namespace will break the compilation

    public class Program
    {
        public void Main()
        {
            new ServiceCollection()
                .AddScoped<IShow1, Show1>();
        }
    }
}

internal record Show1(int ShowId, ...);

или перемещение записи в какое-то пространство имен:

// in Program.cs
app.Run();

namespace MyNamespace
{
    internal record Show1(...);
}

В вашем текущем коде internal record Show1 приводит к классу записи, сгенерированному в глобальном пространстве имен, что приводит к поведению, которое вы наблюдаете.

Спасибо вам за разъяснение! Я хотел знать, что происходит и почему. Я ценю это.

Rod 05.08.2024 04:29

Другие вопросы по теме