2015-06-28 8 views
24

W mojej aplikacji ASP.Net MVC, mam pewien plik widoku (.cshtml), który ma odniesienie do biblioteki zewnętrznej, która zostanie załadowana w środowisku wykonawczym. więc po uruchomieniu aplikacji ładuję zespół przez Assembly.Load i rejestruję kontrolery według własnego klienta ControllerFactory i wszystko jest w porządku.Odwołanie do zestawu w mvc w czasie wykonywania

Ale w niektórych poglądów, które ma odniesień do załadowane dynamicznie montażu, rzuca:

Compiler Error Message: CS0234: Typ lub obszaru nazw „MyDynamicNamespace” nie istnieje w obszarze nazw „MojaApl” (czy brakuje odniesienia do zestawu?)

wyjątek, który mówi, że kompilator maszynki do golenia nie może rozwiązać powiązanego zestawu.

Moje pytanie jest to, że istnieje sposób, aby zarejestrować zespół w czasie wykonywania, aby kompilator brzytwy mógł uzyskać do niego dostęp i go rozwiązać?

Wskazówka, że nie mogę używać BuildManager.AddReferencedAssembly metody, ponieważ mój zespół ma zostać załadowany po starcie aplikacji, a BuildManager nie obsługuje.

+1

Nie jest jasne, dlaczego wymagane jest, aby zespół był ładowany po uruchomieniu aplikacji? Nie byłoby to normalne zastosowanie w przypadku bibliotek zewnętrznych. – Claies

+2

to coś w rodzaju wtyczki lub pomyśl o modułowych aplikacjach internetowych, takich jak cms sad. w rzeczywistości zestaw z jego widokami przychodzi w czasie wykonywania, który daje użytkownik! :) –

+1

Nie sądzę, że jest to możliwe, ponieważ podczas korzystania z Roslyn w środowisku dnx dynamiczny kompilator szuka rozwiązania zależności przy użyciu project.json jako część procesu kompilacji. Twój dynamicznie ładowany zespół nie będzie wymieniony w projekcie.json, a zatem kompilator zawiedzie. Sądzę, że teoretycznie byłoby możliwe dynamiczne dostosowanie projektu project.json przed odzwierciedleniem nowej zależności po starcie i przed załadowaniem widoku, ale szczerze mówiąc nie mam pojęcia, czy to zadziała, a w najlepszym przypadku będzie to hack. Nawet gdyby zadziałało, mogłoby to przerwać w przyszłości. –

Odpowiedz

9

1) Nie polecam posiadania widoków bezpośrednio przy użyciu odnośników zewnętrznych lub dynamicznie ładowanych odniesień zewnętrznych. Rozwijaj to, ponieważ twój widok współdziała z kontrolerem. Spraw, aby kontroler podawał obiekt danych do widoku, który jest znany w czasie kompilacji przez aplikację (innymi słowy, obiekt znany Twojej aplikacji internetowej w czasie kompilacji). Ma to na celu całkowite wyizolowanie (abstrakcji) specyficznej dla danego biznesu wtyczki z widoku. Następnie zmuś kontroler do interakcji z "wtyczką".

2) Nie wiem, jak działa "fabryka niestandardowa", ale obecnie nie budujemy już żadnych "fabryk niestandardowych". Zamiast tego wykorzystujemy kontenery wtrysku zależnego, takie jak Microsoft Unity (lub Ninject, Castle Windsor itp.). Tworzenie "niestandardowych fabryk" jest bardzo staromodne i zasadniczo wymyśla się na nowo koło, które zostało rozwiązane za pomocą wtrysku zależności.

3) W miarę dynamicznie ładuje zespoły zewnętrznych, ja nie wiem, czy masz to prawo, ale tu jest link:

Dynamically load a type from an external assembly

4) Zazwyczaj konstrukcja wtyczki naraża interfejsów, które są znane do głównej aplikacji internetowej w czasie kompilacji. To, co ukrywa projekt wtyczki, to implementacja, która może zmieniać się z jednej wtyczki na drugą. Ważne jest to, że każda wtyczka implementuje te same publiczne interfejsy, które są oczekiwane przez twoją główną aplikację internetową. Zwykle te interfejsy będą dostępne w oddzielnym projekcie "wspólnym", do którego odwołuje się zarówno główna aplikacja internetowa, jak i wtyczka implementująca te interfejsy. Dlatego z Twojej głównej aplikacji internetowej dowiesz się, jakie są publiczne interfejsy twoich wtyczek, możesz dynamicznie załadować zewnętrzny zestaw i użyć C# do odbicia, aby znaleźć klasy, które implementują te interfejsy i załadują je do twojego kontenera wtrysku zależności. Podobnie każdy, kto będzie chciał opracować wtyczkę do twojej aplikacji internetowej, będzie musiał wdrożyć interfejsy zdefiniowane w twoim "wspólnym" projekcie.

Uwaga: "Common" to po prostu losowa nazwa nadana projektowi. Możesz nazwać go "PluginInterface" lub cokolwiek chcesz.

Po tym, posiadanie kontrolera do pobrania, czego potrzebuje, z pojemnika z wtyczką zależności jest banalne.

Uwaga: Twoje interfejsy wtyczek prawdopodobnie będą zawierać elementy wejściowe i wyjściowe. Podmioty te są udostępniane głównej aplikacji internetowej i wtyczce. W takim przypadku, ponieważ te elementy są częścią twoich interfejsów, muszą być w projekcie "Wspólnym". Możesz ulec pokusie, aby twój kontroler zwrócił te jednostki bezpośrednio do twojego widoku, ale wtedy nie będziesz miał idealnej abstrakcji między twoim widokiem a twoją wtyczką. Brak doskonałych abstrakcji jest kolejną dyskusją.

Mam nadzieję, że pomoże!

+1

Twoje 3 nie ma sensu w tej sytuacji, ponieważ to pytanie jest oparte na założeniu, że musisz wpłynąć na dynamiczny proces budowania asp.net –

+2

Pytanie OP dotyczy "wzoru projektu wtyczki", a ja dostarczyłem informacje na temat właściwą drogę. Nie ma to nic wspólnego z "dynamicznym procesem budowania ASP.NET". Podtrzymuję moją odpowiedź. OP miał nadzieję, że mógłby użyć 'BuildManager' do implementacji swojego wzoru projektowania wtyczek, ale jak odkrył, nie ma to z tym nic wspólnego. – TchiYuan

+2

@Tchi Na początku dziękuję bardzo za odpowiedź. Jest wiele dobrych rzeczy, ale tak naprawdę uważam, że widok akcji powinien mieć dostęp do przestrzeni nazw, które mają działanie, to normalne oczekiwanie. Mam do czynienia z rozszerzonym DDD, aby zapewnić interfejsy commomn, ale nie jest to dobry powód do wysyłania jakichkolwiek odwołań wewnątrz widoku do jego przestrzeni nazw wtyczek lub usług takich jak ViewModels, DataProviders, enums, ... :) –

6

Jako administrator Sys zaleciłbym okres konserwacji, zwłaszcza jeśli zastąpiony plik zawiera coś innego. Nawet jeśli twój okres utrzymania trwa tylko pół godziny, jest to dobra praktyka.

Co do biblioteki DLL i rekompilacji ... zazwyczaj proces roboczy usługi IIS (usługa z pulą aplikacji) będzie przetwarzany w regularnych odstępach czasu na podstawie konfiguracji usług IIS i użycia pamięci. Gdy tak się stanie, aplikacja przekompiluje, jeśli cokolwiek będzie wymagało JIT. Kończy także wszystkie otwarte sesje użytkownika, ponieważ fizycznie zatrzymuje się, a następnie ponownie uruchamia. Proces roboczy monitoruje również katalog główny (jak wspomniano) w przypadku jakichkolwiek zmian w plikach. Jeśli zostaną znalezione, następuje ponowna kompilacja. Tylko dlatego, że zmieniona jest zależność, nie wymusza rekompilacji. Jeśli wstępnie skompilujesz bibliotekę DLL, jedyną rzeczą, jaka pozostała do skompilowania, jest dowolny kod wewnątrz twojego rzeczywistego pliku ASPX, a to wykorzystuje JIT, który kompiluje za każdym razem. Z tego, co opisałeś IIS nie powinien rekompilować lub restartować, brzmi jak inny problem, w którym IIS zwisa podczas wymiany pliku. Może zajść potrzeba zaangażowania administratora sys, aby przejrzał dzienniki IIS.

Powodzenia!

http://msdn.microsoft.com/en-us/library/ms366723.aspx

http://msdn.microsoft.com/en-us/library/bb398860.aspx

+0

Właściwie restartuję 'IIS' ręcznie, ale nie jest to dokładnie to, czego chcę. Mam nadzieję, że pewnego dnia otrzymam rozwiązanie lub ktoś mi pomoże. Dziękuję @Farhad –

2

Oto pamiętać, że może pomoże: Jeśli nie ładują swoje zespoły z katalogu /bin, trzeba upewnić się, że ścieżka do zgromadzeń jest wykrywalny:

AppDomain.CurrentDomain.AppendPrivatePath(path_to_your-dyna_assembly); 
+2

Dziękuję za uwagę Javad, ale niestety to mi nie pomaga, zawsze jest problem. montaż jest wykrywalny, nawet gdy ładują się ze ścieżki, która została oznaczona jako ''. i dodatkowo mam wdrożony resolver montażu, który działa dobrze dla mnie. ale kiedy jakakolwiek strona zostanie skompilowana, kontekst kompilatora ('BuildManager') nie ma dostępu ani odniesienia do złożenia. –

Powiązane problemy