Autofac DI problem ze wstrzykiwaniem

Autofac DI problem ze wstrzykiwaniem
Odyn
  • Rejestracja:ponad 16 lat
  • Ostatnio:ponad 5 lat
  • Postów:493
0

Hej.

Tworzę aplikację w której chciałbym wstrzyknąć swoją klasę do Maina() i tam wykorzystać swoje metody.

Posiadam klase EnduroService która jest następująca:

Kopiuj
 public class EnduroService : IEnduroService
    {
        public readonly IGPXParserService _gpxParser;
        public readonly IDistanceService _distanceService;
        public readonly IElevationService _elevationService;
        public readonly ISpeedService _speedService;
        public readonly ITimeService _timeService;
        public readonly IEnumerable<Trackpoint> _node;

        // Inversion of Control here
        public EnduroService(IGPXParserService parser, IDistanceService distance, 
            IElevationService elevation, ITimeService time, string path)
        {
            _gpxParser = parser;
            _distanceService = distance;
            _elevationService = elevation;
            _timeService = time;
            _speedService = new SpeedService(distance, time);
            _node = _gpxParser.ReadGPXFile(path).ToList();
        }

        public IDictionary<string, object> DisplayAllCalculations()
        {}
}

Klasa EnduroService wykorzystuje wiele różnych innych services. Każda z nich ma swój oddzielny Interfejs.

Następnie klasę EnduroService chciałbym wstrzyknąć do metody Main() i tam wykonać pewne operacje.

Stworzyłem sobie klasę ContainerConfig

Kopiuj
 public static class ContainerConfig
    {
        public static IContainer Configure()
        {
            var builder = new ContainerBuilder();

            Assembly executingAssembly = Assembly.GetExecutingAssembly();

            builder.RegisterAssemblyTypes(executingAssembly).AsSelf().AsImplementedInterfaces();


            builder.RegisterType<EnduroService>().AsImplementedInterfaces().SingleInstance();
            builder.RegisterType<DistanceService>().AsImplementedInterfaces().SingleInstance();
            builder.RegisterType<TimeService>().AsImplementedInterfaces().SingleInstance();
            builder.RegisterType<SpeedService>().AsImplementedInterfaces().SingleInstance();
            builder.RegisterType<ElevationService>().AsImplementedInterfaces().SingleInstance();
            builder.RegisterType<GPXParserService>().AsImplementedInterfaces().SingleInstance();


            var container = builder.Build();
            return container;
        }
    }

Gdzie rejestruje swoje typy i buduje kontenery.

Nastepnie w metodzie Main() swojej aplikacji konsolowej robię nastepujące rzeczy:

Kopiuj
public class Program
    {
        private static ILogger _logger;
        public readonly IEnduroService _enduroService;
        public readonly IGPXParserService _gpxParser;
        public readonly IDistanceService _distanceService;
        public readonly IElevationService _elevationService;
        public readonly ISpeedService _speedService;
        public readonly ITimeService _timeService;
        public readonly IEnumerable<Trackpoint> _node;

        private const string pathToGPXFile = @"DATA\DH.gpx";

        public Program(IGPXParserService parser, IDistanceService distance,
           IElevationService elevation, ITimeService time, string path)
        {
            _gpxParser = parser;
            _distanceService = distance;
            _elevationService = elevation;
            _timeService = time;
            _speedService = new SpeedService(distance, time);
            _node = _gpxParser.ReadGPXFile(path).ToList();
        }

        static void Main(string[] args)
        {
            _logger = new LoggerConfiguration()
                .MinimumLevel.Debug()
                .WriteTo.RollingFile(@"Log\ApplicationLog.txt", retainedFileCountLimit: 7)
                .CreateLogger();

            var container = ContainerConfig.Configure();

            //_enduroCalculations = new EnduroService(new GPXParserService(), 
            //    new DistanceService(), new ElevationService(), 
            //    new TimeService(), pathToGPXFile);

            //var calculations = _enduroCalculations.DisplayAllCalculations();


            using (var scope = container.BeginLifetimeScope())
            {
                var injection = scope.Resolve<IEnduroService>();

                var calculations = injection.DisplayAllCalculations();

                calculations.ToList().ForEach(item => Console.WriteLine("{0}: {1}", item.Key, item.Value));
                calculations.ToList().ForEach(item => _logger.Information("{0}: {1}", item.Key, item.Value));
            }

            //calculations.ToList().ForEach(item => Console.WriteLine("{0}: {1}", item.Key, item.Value));
            //calculations.ToList().ForEach(item => _logger.Information("{0}: {1}", item.Key, item.Value));

            Console.ReadLine();
        }
    } 

Niestety zamiast poprawnych obliczeń otrzymuje wyjątek taki jak:

Kopiuj
 {"None of the constructors found with 'Autofac.Core.Activators.Reflection.DefaultConstructorFinder' on type 'Trails_Services.Display.EnduroService' can be invoked with the available services and parameters:\r\nCannot resolve parameter 'System.String path' of constructor 'Void .ctor(Trails_Interfaces.IParser.IGPXParserService, Trails_Interfaces.ICalculations.IDistanceService, Trails_Interfaces.ICalculations.IElevationService, Trails_Interfaces.ICalculations.ITimeService, System.String)'."}

Czy ktoś mógłby mi wytłumaczyć co robię źlę i jak to naprawić? Nie do końca czuję jak ten cały Autofac DI działa.


edytowany 1x, ostatnio: DibbyDum
DibbyDum
  • Rejestracja:ponad 12 lat
  • Ostatnio:ponad rok
  • Lokalizacja:Polska, Kraków
2

Masz w konstruktorze string path Autofac nie wie co ma z tym zrobić.
http://docs.autofac.org/en/latest/register/parameters.html


Yubby dibby dibby dibby dibby dibby dibby dum..
edytowany 1x, ostatnio: DibbyDum
Odyn
  • Rejestracja:ponad 16 lat
  • Ostatnio:ponad 5 lat
  • Postów:493
0

Właśnie nie wiem czy koniecznie muszę robić tam ten konstruktor bo tak na prawdę na poziomie klasy Progrm chce używać tylko EnduroService.

Więc wystarczy mi wstrzyknąć EnduroService przez konstruktor?


DibbyDum
  • Rejestracja:ponad 12 lat
  • Ostatnio:ponad rok
  • Lokalizacja:Polska, Kraków
5

No ale to właśnie jest problem z utworzeniem EnduroService bo tam jest parametr string path, więc nie wstrzykniesz EnduroService bo Autofac nie potrafi tego utworzyć.


Yubby dibby dibby dibby dibby dibby dibby dum..
fasadin
  • Rejestracja:prawie 14 lat
  • Ostatnio:prawie 3 lata
  • Postów:4882
1

najszybszym rozwiazaniem zapewne bedzie zrobienie jakiegos interfejsu do stringa ALE NIE POLECAM TAK TEGO ROBIC. Nie jest to dobra droga (to powstalo zeby Ci to wybic z glowy, ale zapomnialem o tym napisac :D)

sadze ze nie jestes pierwsza osoba ktora zatkela sie z tym problemem
https://stackoverflow.com/questions/9066200/passing-parameters-to-constructors-using-autofac

dostales rozniew od @DibbyDum linka co trzeba zrobic

edytowany 6x, ostatnio: DibbyDum
somekind
Moderator
  • Rejestracja:około 17 lat
  • Ostatnio:7 dni
  • Lokalizacja:Wrocław
2

Dlaczego Program ma w ogóle jakieś niestatyczne pola i konstruktor?

fasadin napisał(a):

najszybszym rozwiazaniem zapewne bedzie zrobienie jakiegos interfejsu do stringa

WHAT THE FAAAAAAAAAAAAAAAAAAAAAAK???????????????????????!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

edytowany 1x, ostatnio: somekind
fasadin
czekaj, bo zle to napisalem juz edytuje
fasadin
juz
Odyn
  • Rejestracja:ponad 16 lat
  • Ostatnio:ponad 5 lat
  • Postów:493
0

Dzięki, patrze właśnie na to wszystko teraz. Link do Stack Overflow nie działa :P


DibbyDum
Poprawiłem link.
Odyn
  • Rejestracja:ponad 16 lat
  • Ostatnio:ponad 5 lat
  • Postów:493
0

Okej udało mi się to rozwiązać z Waszą pomocą :)

Zmodyfikowałem klasę ContainersConfig i stworzyłem Typowane parametry

Kopiuj
 public static class ContainerConfig
    {
        public static IContainer Configure()
        {
            var builder = new ContainerBuilder();

            Assembly executingAssembly = Assembly.GetExecutingAssembly();

            builder.RegisterAssemblyTypes(executingAssembly).AsSelf().AsImplementedInterfaces();

            builder.RegisterType<EnduroService>().AsImplementedInterfaces().SingleInstance().WithParameter(new TypedParameter(typeof(string), @"DATA\DH.gpx"));
            builder.RegisterType<DistanceService>().AsImplementedInterfaces().SingleInstance();
            builder.RegisterType<TimeService>().AsImplementedInterfaces().SingleInstance();
            builder.RegisterType<SpeedService>().AsImplementedInterfaces().SingleInstance();
            builder.RegisterType<ElevationService>().AsImplementedInterfaces().SingleInstance();
            builder.RegisterType<GPXParserService>().AsImplementedInterfaces().SingleInstance().WithParameter(new TypedParameter(typeof(string), @"DATA\DH.gpx"));


            var container = builder.Build();
            return container;
        }
    }

Nie wiem czy to jest dobre rozwiązanie, czy może da sieto zrobić jakoś lepiej/ładniej ale działa :) 

edytowany 1x, ostatnio: DibbyDum
0
somekind napisał(a):

Dlaczego Program ma w ogóle jakieś niestatyczne pola i konstruktor?

Nie wiesz, że można w klasie robić niestatyczne pola oraz definiować konstruktor że tak Ciebie to dziwi? Konwencja wymaga tylko metody statycznej Main (która jest oznaczane w CIL jako .entrypoint) a gdzie ją umieścisz to nie ma znaczenia. Co więcej możesz mieć więcej punktów wejścia w programie i sterować parametrami kompilatora w celu wyboru konkretnego.

somekind
Moderator
  • Rejestracja:około 17 lat
  • Ostatnio:7 dni
  • Lokalizacja:Wrocław
0

Wiem, tylko nie wiem po co sobie życie utrudniać i pisać spaghetti. Dlatego spytałem. ;]

Widzę, że mamy nowego newbie, który chętnie się dzieli wiedzą z książek. ;)

edytowany 1x, ostatnio: somekind
0

Widzę, że mamy starego użytkownika która nie posiada nawet wiedzy z książek oraz potrafi ocenić cudza wiedzę na podstawie jednego postu.

somekind
Nie nazwałbym tego wiedzą. Skończ trolować i offtopować.

Zarejestruj się i dołącz do największej społeczności programistów w Polsce.

Otrzymaj wsparcie, dziel się wiedzą i rozwijaj swoje umiejętności z najlepszymi.