Saya menggunakan Unity Microsoft untuk injeksi ketergantungan dan saya ingin melakukan sesuatu seperti ini:
IDataContext context = _unityContainer.Resolve<IDataContext>();
var repositoryA = _unityContainer.Resolve<IRepositoryA>(context); //Same instance of context
var repositoryB = _unityContainer.Resolve<IRepositoryB>(context); //Same instance of context
IDataContext context2 = _unityContainer.Resolve<IDataContext>(); //New instance
var repositoryA2 = _unityContainer.Resolve<IRepositoryA>(context2);
RepositoryA
dan RepositoryB
keduanya memiliki konstruktor yang mengambil IDataContext
parameter, dan saya ingin Unity menginisialisasi repositori dengan konteks yang saya berikan. Perhatikan juga bahwa IDataContext
tidak terdaftar dengan Unity (Saya tidak ingin 3 contoh IDataContext
).
Foo(string name, int address) { ... }
container.Resolve<IFoo>(new ParameterOverrides { { "name", "bar" }, { "address", 42 } });
<2 sen>
Bagaimana jika Anda kemudian memutuskan untuk menggunakan layanan berbeda yang membutuhkan lebih atau kurang dari sekedar konteks?
Masalah dengan parameter konstruktor dan IoC adalah bahwa parameter pada akhirnya terikat pada jenis beton yang digunakan, bukan menjadi bagian dari kontrak yang ditentukan oleh antarmuka layanan.
Saran saya adalah Anda menyelesaikan konteksnya juga, dan saya yakin Unity harus memiliki cara bagi Anda untuk menghindari pembuatan 3 instance darinya, atau Anda harus mempertimbangkan layanan pabrik yang memiliki cara bagi Anda untuk membuat objek.
Misalnya, bagaimana jika Anda kemudian memutuskan untuk membangun repositori yang tidak bergantung pada database tradisional sama sekali, melainkan menggunakan file XML untuk menghasilkan dummy-data untuk pengujian? Bagaimana Anda akan memberi makan konten XML ke konstruktor itu?
IoC didasarkan pada kode decoupling, dengan mengikat tipe dan semantik argumen ke tipe konkret, Anda benar-benar belum melakukan decoupling dengan benar, masih ada ketergantungan.
"Kode ini dapat berbicara dengan semua jenis repositori mungkin, selama mengimplementasikan antarmuka ini .... Oh, dan menggunakan konteks data".
Sekarang, saya tahu bahwa kontainer IoC lain memiliki dukungan untuk ini, dan saya juga memilikinya di versi pertama saya, tetapi menurut saya, itu tidak termasuk dalam langkah resolusi.
</ 2 sen>
sumber
Terima kasih teman-teman ... milikku mirip dengan kiriman oleh "Exist". Lihat di bawah:
IUnityContainer container = new UnityContainer(); container.LoadConfiguration(); _activeDirectoryService = container.Resolve<IActiveDirectoryService>(new ResolverOverride[] { new ParameterOverride("activeDirectoryServer", "xyz.adserver.com") });
sumber
Anda dapat menggunakan InjectionConstructor / InjectionProperty / InjectionMethod bergantung pada Arsitektur Injeksi Anda dalam ResolvedParameter <T> ("name") untuk mendapatkan instance dari Objek yang telah didaftarkan sebelumnya di penampung.
Dalam kasus Anda, Objek ini harus terdaftar dengan sebuah Nama, dan untuk insance yang sama Anda memerlukan ContainerControlledLifeTimeManager () sebagai LifeTimeManager.
_unityContainer.RegisterType<IDataContext,DataContextA>("DataContextA", new ContainerControlledLifeTimeManager()); _unityContainer.RegisterType<IDataContext,DataContextB>("DataContextB"); var repositoryA = _unityContainer.Resolve<IRepositoryA>(new InjectionConstructor( new ResolvedParameter<IDataContext>("DataContextA"))); var repositoryB = _unityContainer.Resolve<IRepositoryB>(new InjectionConstructor( new ResolvedParameter<IDataContext>("DataContextA"))); var repositoryA2 = _unityContainer.Resolve<IRepositoryA>(new InjectionConstructor( new ResolvedParameter<IDataContext>("DataContextB")));
sumber
Resolve
mengambil koleksiResolverOverride
, danInjectionConstructor
bukanResolverOverride
.Jawaban yang sangat singkat adalah: tidak. Unity saat ini tidak memiliki cara untuk melewatkan parameter ke konstruktor yang tidak konstan atau diinjeksi, yang dapat saya temukan. IMHO itulah satu-satunya hal terbesar yang hilang, tapi saya pikir itu adalah desain daripada kelalaian.
Seperti yang dicatat oleh Jeff Fritz, secara teori Anda dapat membuat pengelola seumur hidup khusus yang mengetahui contoh konteks mana yang akan dimasukkan ke dalam berbagai jenis, tetapi itu adalah tingkat pengkodean keras yang tampaknya meniadakan tujuan penggunaan Unity atau DI di tempat pertama.
Anda bisa mundur selangkah dari DI penuh dan membuat implementasi repositori Anda bertanggung jawab untuk menetapkan konteks datanya sendiri. Konteks contoh masih bisa diselesaikan dari wadah tetapi logika untuk memutuskan mana yang akan digunakan harus pergi ke dalam pelaksanaan repositori. Ini tidak murni, tentu saja, tapi itu akan menghilangkan masalah.
sumber
Alternatif lain yang dapat Anda gunakan (tidak benar-benar tahu apakah ini praktik yang baik atau tidak) adalah membuat dua kontainer dan mendaftarkan satu contoh untuk masing-masing:
IDataContext context = _unityContainer.Resolve<IDataContext>(); _unityContainer.RegisterInstance(context); var repositoryA = _unityContainer.Resolve<IRepositoryA>(); //Same instance of context var repositoryB = _unityContainer.Resolve<IRepositoryB>(); //Same instance of context //declare _unityContainer2 IDataContext context2 = _unityContainer2.Resolve<IDataContext>(); //New instance _unityContainer2.RegisterInstance(context2); var repositoryA2 = _unityContainer2.Resolve<IRepositoryA>(context2); //will retrieve the other instance
semoga ini membantu juga
sumber
NotDan, saya pikir Anda mungkin telah menjawab pertanyaan Anda sendiri di komentar ke lassevk.
Pertama, saya akan menggunakan LifetimeManager untuk mengelola siklus hidup dan jumlah instance IDataContext yang dibuat oleh Unity.
http://msdn.microsoft.com/en-us/library/cc440953.aspx
Sepertinya
ContainerControlledLifetimeManager
objek tersebut akan memberi Anda manajemen instance yang Anda butuhkan. Dengan LifetimeManager tersebut di tempat, Unity harus menambahkan instance IDataContext yang sama ke semua objek yang memerlukan dependensi IDataContext.sumber