2009-02-02 35 views
32

Bir yükleme sırasında yükleme kodunda herhangi bir şey yapmadan bir kod çalıştırmak mümkün mü? Aradığım şey, bir türdeki statik bir kurucu gibi..Net: Derleme yüklendiğinde çalışma kodu

Örn:

Montaj A Montaj B bilmediği, ancak A. Montaj A B yüklü ise B hakkında bazı şeyleri bilmelidir hakkında B biliyor. Assembly B çalışma zamanı tarafından (başvurulan veya açık) yüklendiğinde, Assembly A'da bir yöntemi çağıran bir kod (statik yöntem veya öznitelik) yürütmek istiyorum.

Bu sorunun kök nedeni bilinmiyor Arabirimler olarak derleme zamanında bilinmeyen B türlerini içeren A türünü serileştirirken karşılaşılan türler.

cevap

37

CLR module initializers destekler hakkında bilmek gerek kalmadan montaj B yük olacağını yapabilirsiniz. Kullanmak için C++/CLI kodunu veya ilasm.exe'yi kesmeniz gerekir.

+9

https://github.com/Fody/ModuleInit –

+2

@RichardCollette ile hack gerekli değil, hala hack yapıyor, ancak Fody sadece yapmak için kolaylaştırmak için inşa sürecine hack otomatize ediyor. –

6

(düzenleme - C# için geçerlidir; bir C++ yaklaşım için, this answer bakınız)

Temelde, hiçbir: yapamazsın. Bu büyük bir saldırı yüzeyi ve izin verilmez. Init kodunun yürütülmesini sağlayan bazı B türlerine statik bir ctor koymak isteyebilirsiniz, ancak bu konuyla ilgili ...

+5

Neden bir saldırı yüzeyi? –

+1

Görünüşe göre, kodları bilerek çağırmayacak bir kodun - izlenmesi zor, vb. - bu tür bir iş parçacığının sorması gereken bir soru olsun… Belki de düzgün bir şekilde seslendirme yapamıyorum. bana karşı ses çıkarır. Ancak bunu yapamayacağınız bir şey yoktur; -p –

+0

Üzerinde herhangi bir bilgi olup olmadığını biliyor musunuz (modül başlatıcıları yükte değil, statik kuruculardan önce çalışmaktadır), bu yüzden eğer kodlar ilginçse Yükleme sırasında çalıştırın. Bu çok yakın soruyu da yanıtlayıp cevaplayamayacağınızı kontrol ederseniz - http://stackoverflow.com/questions/24718917/can-a-call-to-assembly-loadbyte-raise-the-appdomain-assemblyresolve-event/24719526? noredirect = 1 # comment38423553_24719526 –

3

Bu sorunu hafifletmek için serileştirme yaklaşımınızı yeniden gözden geçirmelisiniz. Eğer ISerializable ve SerializableAttribute özniteliği kullanılarak serialize, bunu böyle seri grafik gerektiğinde montaj A şimdiye açıkça montaj B.

+0

Bu yöntemi kullanarak B Grubunu nasıl tanımlayabilir ve yükleyebilirim? –

+0

Kullanarak serileştirirseniz, bir BinaryFormatter, serileştirme grafiğinizde ISerializable'ı uygulayabilen herhangi bir tür, deserialize sırasında çağırıcılarını çağırır, hangi ihtiyacınız olursa olsun kodu arayabilirsin. Seri hale getirdiğinizde, arabirim için seri hale getirme sorguları ... –

+0

... A'nın yalnızca bir arabirim tarafından B türlerine başvurup göndermediği önemli değil, doğru şekilde serileştirilecekler. –

5

.Net'te statik yapıcılar kullanabilirsiniz, ancak maalesef istediğiniz şeyi yapmıyorlar. Statik kurucular sadece bir tür kullanılmadan önce yürütülür. Ayrıntılar için bkz. http://msdn.microsoft.com/en-us/library/k9x6w0hc(VS.80).aspx.

AppDomain'in AssemblyLoad olayına abone olmanız için biraz mesafe alabilirsiniz. Bakınız http://msdn.microsoft.com/en-us/library/system.appdomain.assemblyload.aspx.

Etkinlik işleyicinizde yeni yüklenen montajı yansıtabilir ve istediğiniz kodu çalıştırabilirsiniz.

+0

Maalesef, 30 adet garnizonun sadece bir tanesi bu kayıt işleminin yapılmasına ihtiyaç duyduğundan, AssemblyLoad aşırı derecede aşırıya kaçabilir. –

0

Karma bir aksamı kullanarak, DllMain'in bir derleme yüklemesinde çalışmasını sağlayabilirsiniz. Bir .NET Meclisi başlatmak için 3 seçenek vardır

3

: başlatılması için sizin Meclis'te

  1. Statik bir işlev Init() veya Ana (yazma) ve C# kodundan yansıma yoluyla bu işlevi dediğimiz bu Meclisi yükler.
  2. Kodunuzu DllMain() içine yerleştirdiğiniz Yönetilen C++ Derlemesi yazın. Dikkatli olun çünkü kodunuz Loader Lock'da (bazı DLL'lerin yüklenmesi gibi) yasaklanmış olan bazı şeylerin yasaklanmasıyla gerçekleştirilecektir. Ancak, HERHANGİ başlatma işlemini yapan yeni bir konu başlatabilirsiniz. (Yaklaşık LoaderLock: https://msdn.microsoft.com/en-us/library/ms173266.aspx) (Yaklaşık DllMain'de: C# to C++/CLI to C DLL System.IO.FileNotFoundException)
  3. Sen saf C# Meclisi derlemek ve burada açıklanan gibi bir modül başlatıcısı kodu eklemek için derlenmiş DLL değiştirin: http://einaregilsson.com/module-initializers-in-csharp/ Bu yöntemin dezavantajı olduğunu Derleme işlemin içine yüklendiğinde başlatma işlevi hemen çağrılmaz. Ancak mecliste başka bir şeyden önce ilk önce erişilir.
+0

1) tartışmasız "yükleme kodunda herhangi bir özel bir şey yapmadan" tatmin etmiyor mu? _ – MickyD

+0

Yükleme kodunu değiştirmemenizin tek yolu, seçenek 2'dir.) – Elmue

+0

Evet, seçenek 2'yi çok beğeniyorum – MickyD

İlgili konular