lagi tentang konfigurasi log4net dan Unity IOC

Saya telah menemukan beberapa pertanyaan yang ada di berbagai situs dan jawabannya tampaknya diputar oleh l4n pejabat menuju nilai pembungkus ringan yang 'adalah' log4net (tidakkah Anda mengerti?) dan pemikiran serupa -fakta yang membingungkan.

Namun tampaknya apa yang diminta pengguna (dan ini pertanyaan saya) adalah bagaimana menyesuaikan model objek log4net ke dalam urutan registertype/registerinstance di antarmuka konfigurasi yang lancar.

Tujuannya di sini bukan untuk membungkus ulang l4n, tetapi hanya untuk mengambil referensi yang layak yang tidak memerlukan pembajakan aliran lancar.

contoh yang buruk, saya ingin mendapatkan referensi ke instance ILog yang dikonfigurasi dari metode LogManger.GetLogger dan memasukkannya ke dalam aliran lancar cukup awal untuk memasukkannya ke properti objek hilir saya.

Jadi sebagai tanggapan atas satu saran yang tidak sabar, saya mencoba membuat instance ILog normal dengan cara kanonik:

log4net.Config.XmlConfigurator.Configure();
static readonly log4Net.Ilog Log = LogManager.GetLogger(thatlongassemblyreflectionstuff);

Jadi tampaknya sepele (dalam arti sebenarnya mudah) untuk menambahkan referensi itu ke wadah Unity dan melanjutkan hidup saya yang indah.

Namun, tanda tangan untuk metode RegisterInstance menginginkan 'Jenis' bukan antarmuka.

Bagi mereka yang belum mencari melalui model objek log4net, afficiananderosnya benar: l4n adalah 'pembungkus' dan Anda tidak bisa mendapatkan 'tipe' sebenarnya untuk benda Log.

Jadi sekarang saya harus mengujinya. Dan tahukah Anda apa maksudnya, hal ini bisa memakan waktu satu menit, namun kemungkinan besar akan memakan waktu satu atau empat jam (kesamaan seperti ejaan 'jam' dan 'empat' tidak pernah terjadi secara kebetulan dalam kehidupan nyata).

Namun, yang berikut ini, kecuali bagian yang dihilangkan tentang pengaturan kanonik, berhasil:

container
  .RegisterInstance("Logger", Log, new ContainerControlledLifetimeManager())
.RegisterType<IControllerContext, ControllerContext>
(
   "CtlrCtx", 
   new ContainerControlledLifetimeManager(), 
   new InjectionConstructor(new ResolvedParameter<IMessageBuilder>("MsgBldr")),
   new InjectionProperty("Log",new ResolvedParameter<ILog>("Logger"))
);

Jadi kode hash untuk objek Log asli dan objek Log yang dimasukkan ke dalam properti objek Konteks kecil saya yang luar biasa adalah identik.

Namun...

Proses injeksi mengharuskan saya mengekspos properti Log dari objek Konteks melalui antarmukanya, yang berarti objek tersebut tidak lagi menjadi objek statis. Dan apakah objek log4net ILog itu statis tampaknya menjadi faktor penentu apakah objek tersebut dapat diserialkan dan dapat digabungkan antar rakitan tanpa peringatan dramatis 'waktu proses akan menjadi tidak stabil' (yang benar-benar hanya berarti bagi penggemar Matrix).

Berkecil hati, meskipun tidak tergoyahkan, saya menggunakan 'properti to dengan bidang pendukung' yang bagus dari Resharper dan mengatur bidang pendukung menjadi statis sementara properti Antarmuka tetap non-statis. Itu dibangun dengan baik dan pengujiannya berjalan ramah lingkungan.

Jadi saya bahkan melakukan pembangunan kembali dan berhasil. Jadi mungkin ketika ini muncul ke tes integrasi saya akan menyelinap melewati bencana log4net yang tidak dapat diserialkan.

Jadi mungkin ini bisa membantu

Terima kasih

status


person Stato Machino    schedule 24.08.2009    source sumber
comment
Bukanlah praktik normal untuk memiliki logger sebagai variabel instan - mereka biasanya merupakan variabel statis (yaitu kelas) dan tetap diimplementasikan sebagai variabel tunggal. Jadi menurut saya Anda tidak mendapat manfaat apa pun dengan mengambilnya dari wadah Unity - mengapa Anda perlu melakukannya?   -  person Vinay Sajip    schedule 09.10.2009
comment
'Mengapa?' jelas merupakan pertanyaan yang masuk akal. Jawabannya berkaitan dengan satu titik konfigurasi. menggunakan logger apa pun 'di mana pun' akan menjadi beban konfigurasi yang nyata dan pemeliharaannya sangat berat di bagian 'tidak' jika menyangkut kesenangan.   -  person Stato Machino    schedule 10.02.2011


Jawaban (2)


Apakah menggunakan InjectionFactory di Unity 2 akan membantu? (lihat pertanyaan ini). Maka kode konfigurasi Anda akan terlihat seperti ini:

IUnityContainer container = new UnityContainer();
container.RegisterType<ILog>(new InjectionFactory(factory => LogManager.GetLogger()));

Kemudian Anda mengambil logger dengan panggilan biasa ke Resolve():

ILog logger = container.Resolve<ILog>();
logger.Log(Level.Debug, "Hello world");

Anda mungkin juga dapat mengonfigurasi masa pakai logger menjadi ContainerControllerLifetimeManager, untuk menjadikannya instance tunggal, tetapi saya belum memverifikasinya.

person David Keaveny    schedule 07.02.2011
comment
ini terlihat seperti terkait log4net tetapi berguna untuk contoh objek yang juga dibuat untuk startup. terima kasih. - person Nuri YILMAZ; 30.01.2012

ILog logger = container.Resolve<ILog>();
logger.Log(Level.Debug, "Hello world");

memang berhasil.

Namun, jika Anda memiliki properti untuk logger di suatu kelas, dan ingin memasukkan instance logger ini ke dalamnya, AFAICT tidak akan berfungsi. Saya kira saya mungkin melenceng, tapi saya mencoba menggunakan kembali contoh logger dalam konteks baru. Ini mungkin tidak bisa dibatalkan, jadi saya mungkin harus menyerah untuk menyuntikkannya dan hanya menambahkan baris

ILog logger = container.Resolve<ILog>();

untuk setiap kelas, yang memberi saya hasil yang tampaknya hanya sedikit berbeda dari yang dibuat di setiap kelas....

Saya berharap itu

private ILog Logger {get;set;} 

bisa saja disuntikkan tetapi sepertinya tidak berhasil sama sekali, karena melalui log4net semuanya dilakukan melalui antarmuka dan logger beton bersembunyi di balik tirai dengan Wizard of Oz.

person AllenM    schedule 09.06.2011