myCSharp.de - DIE C# und .NET Community
Willkommen auf myCSharp.de! Anmelden | kostenlos registrieren
 
 | Suche | FAQ

» Hauptmenü
myCSharp.de
» Startseite
» Forum
» FAQ
» Artikel
» C#-Snippets
» Jobbörse
» Suche
» Regeln
» Wie poste ich richtig?
» Forum-FAQ

Mitglieder
» Liste / Suche
» Wer ist wo online?

Ressourcen
» openbook: Visual C#
» openbook: OO
» Microsoft Docs

Team
» Kontakt
» Übersicht
» Wir über uns

» myCSharp.de Diskussionsforum
Du befindest Dich hier: Community-Index » Diskussionsforum » Entwicklung » Rund um die Programmierung » Open Generic in .NET Core DI Container registrieren und auflösen
Letzter Beitrag | Erster ungelesener Beitrag Druckvorschau | Thema zu Favoriten hinzufügen

Antwort erstellen
Zum Ende der Seite springen  

Open Generic in .NET Core DI Container registrieren und auflösen

 
Autor
Beitrag « Vorheriges Thema | Nächstes Thema »
Davaaron
myCSharp.de-Mitglied

Dabei seit: 15.04.2016
Beiträge: 88


Davaaron ist offline

Open Generic in .NET Core DI Container registrieren und auflösen

Beitrag: beantworten | zitieren | editieren | melden/löschen       | Top

Hi,

ich habe einige Klassen und Interfaces (siehe unten), die ich gerne dem DI Container von .NET Core (IServiceCollection) hinzufügen will. Als Erweiterung habe ich Scrutor installiert, damit ich einfacher die benötigten Typen registrieren kann.
Ziel ist es, neben einigen Services auch generische Presenter zur Collection hinzuzufügen, auch welche, die außerhalb der ausführenden Assembly liegen.
Soweit funktioniert auch alles, aber bei einem Konstrukt habe ich das Problem, dass sie anscheinend nicht der Collection hinzugefügt werden. Beim Auflösen bekomme ich eine Fehlermeldung:

"System.ArgumentException: Open generic service type 'Winforms.MVP.UI.IPresenter`2[TView,TModel]' requires registering an open generic implementation type. (Parameter 'descriptors')"

Die Interfaces und Klassen sehen folgendermaßen aus:

C#-Code:
public interface IPresenter<TView, TModel> where TView : IView
        where TModel : BaseViewModel
    {
        TView View { get; set; }

        TModel Model { get; set; }

        IDialogService DialogService { get; }

        INavigationService NavigationService { get; }
        IWizardService WizardService { get; }

        IMediator Mediator { get; }


    }

C#-Code:
public abstract class BasePresenter<V, M> : BasePresenter where V : IView
                                    where M : BaseViewModel
    {


        public new V View { get => (V)_view; set => _view = value; }

        public new M Model { get => (M)_model; set => _model = value; }


        public BasePresenter(V view, M model, INavigationService navigationService,
            IDialogService dialogService, IWizardService wizardService, IMediator mediator, IServiceCollection serviceCollection)
            : base(view, model, navigationService, dialogService, wizardService, mediator, serviceCollection)
        {


        }
    }

    public abstract class BasePresenter : IPresenter<IView, BaseViewModel>
    {
        protected IView _view;
        protected BaseViewModel _model;

        public INavigationService NavigationService { get; }
        public IDialogService DialogService { get; }
        public IWizardService WizardService { get; }
        public IMediator Mediator { get; }
        public IServiceCollection ServiceCollection { get; }

        public BasePresenter(IView view, BaseViewModel model, INavigationService navigationService, IDialogService dialogService,
            IWizardService wizardService, IMediator mediator, IServiceCollection serviceCollection)
        {
            View = view;
            Model = model;
            NavigationService = navigationService;
            DialogService = dialogService;
            WizardService = wizardService;
            Mediator = mediator;
            ServiceCollection = serviceCollection;
        }
}

So registriere ich alle Presenter:

C#-Code:
Container.Scan(scan =>
              scan.FromApplicationDependencies()
               .AddClasses(@class => @class.AssignableToAny(Config.PresenterTypes))
               .AsImplementedInterfaces()
               .WithSingletonLifetime());

            //Oder
            Container.AddTransient(typeof(IPresenter<,>), typeof(BasePresenter<,>));

Config.PresenterTypes:

C#-Code:
        public List<Type> PresenterTypes { get; } = new List<Type>() { typeof(BasePresenter<IView,BaseViewModel>) };

So versuche ich sie aufzulösen:

C#-Code:
  var presenter = container.Get<IPresenter<TestView, TestModel>>();
            var presente2r = container.Get<BasePresenter<TestView, TestModel>>();
            var presente2r3 = container.Get<BasePresenter<IView, BaseViewModel>>();
            var testPresenter = container.Get<TestPresenter>();
            var presenters = container.Get(typeof(IPresenter<,>));
            Assert.IsTrue(presenter != null || testPresenter != null || presenters != null || presente2r != null || presente2r3 != null);

Keine der Auflösungen funktioniert, da, wie ich vermute, kein Presenter gefunden und hinzugefügt wird. Hat jemand einen Typ, wie ich alle Klassen dem Container hinzufügen kann, die entweder von IPresenter oder BasePresenter implementiert bzw. erbt?
Auflösen würde ich dann einen bestimmten Presenter, indem ich den konkreten Implementierungstyp angebe, bspw.

DIContainer.Get<BillpaymentPresenter>();
07.03.2020 19:58 E-Mail | Beiträge des Benutzers | zu Buddylist hinzufügen
Palladin007 Palladin007 ist männlich
myCSharp.de-Mitglied

avatar-4140.png


Dabei seit: 03.02.2012
Beiträge: 1.279
Entwicklungsumgebung: Visual Studio 2019
Herkunft: NRW


Palladin007 ist offline

Beitrag: beantworten | zitieren | editieren | melden/löschen       | Top

Wenn ich dich richtig verstehe, versuchst Du die fertigen nicht generischen Implementierungen mit einem offenen generischen Interface zu registrieren?

Ohne es getestet zu haben fürchte ich, dass das nicht geht.
Wenn Du einen offenen generischen Typ registrierst und eine geschlossene generische Variante davon abfragst, sucht der Contrainer nach einer passenden Klasse, bei der er die generischen Typen setzen kann.
Eine solche Klasse gibt es aber nicht, davon ist ja nichts generisch.

Versuch Mal per Reflection nach allen Implementierungen zu suchen und hole dir dann das konkrete geschlossene Interface (müsste über die InterfaceMap gehen).
Nun hast Du das geschlossen generische Interface und die nicht generische Implementierung und kannst beides simpel registrieren.

Dieser Beitrag wurde 1 mal editiert, zum letzten Mal von Palladin007 am 07.03.2020 20:21.

07.03.2020 20:20 Beiträge des Benutzers | zu Buddylist hinzufügen
Baumstruktur | Brettstruktur       | Top 
myCSharp.de | Forum Der Startbeitrag ist älter als 5 Monate.
Der letzte Beitrag ist älter als 5 Monate.
Antwort erstellen


© Copyright 2003-2020 myCSharp.de-Team | Impressum | Datenschutz | Alle Rechte vorbehalten. | Dieses Portal verwendet zum korrekten Betrieb Cookies. 10.08.2020 17:40