我有一個像下面這樣的通用服務:
public interface ISyncedDataService<T> where T : BaseDBModel
{
Task<int> SaveItem(T item);
Task<int> InsertAllItems(List<T> items);
Task<List<T>> GetItems();
Task<T> GetItem(long primaryKey);
Task<int> DeleteItem(T item);
}
并且有一堆從 BaseDBModel 繼承的類 T1、T2、T3、T4..T20。
我正在使用 Autofac 呼叫如下服務:
using var scope = App.Container.BeginLifetimeScope(); //Container is Autofac.IContainer
var items = await scope.Resolve<ISyncedDataService<T1>>().GetItems(); //T1 inherits BaseDBModel
如果型別 T1...T20 僅在運行時已知,我該如何呼叫 GetItems()?目前我正在使用 if-else 鏈來使其簡單快捷。但是關于我如何動態地做到這一點的好奇心(反射?)
編輯:使用反射時,挑戰在于嘗試動態獲取擴展方法的 MethodInfo 時,該擴展方法也是通用方法。
uj5u.com熱心網友回復:
不能使用反射決議泛型類中的型別引數。
但是要呼叫特定類中的方法,這個使用反射的答案可能會有所幫助。
如何使用反射來呼叫泛型方法?
如果您只想將泛型介面注冊為泛型類。
`builder.RegisterGeneric(typeof(YourGenericClass<>)).As(typeof(YourGenericInterface<>))`
是使用autofac的代碼。
uj5u.com熱心網友回復:
如果您在運行時沒有系結泛型型別,那么您會遇到這種if-else型別檢查模式。我不確定這是否與 Autofac 有很大關系。冒著聽起來很明顯的風險,您可以通過呼叫Resolve回傳物件的非泛型方法來解決這個問題。
object foo = componentContext.Resolve(type);
這是通用的。
您可以做的另一件事是將物件強制轉換回,ISyncedDataService<BaseDBModel>但這僅在您的介面是協變的情況下才有效。宣告如下:
interface ISyncedDataService<out T> where T : BaseDBModel
// and then
var foo = (ISyncedDataService<BaseDBModel>)componentContext.Resolve(type);
同樣,協方差是否對您的界面有意義是您必須決定的。
一些警告.. 希望你沒有在這里使用服務定位器反模式。還要注意范圍的生命周期,您似乎scope在解決依賴項的方法中處理了。默認情況下,這應該與范圍一起終止依賴項。希望依賴項被注冊為更長的壽命。
轉載請註明出處,本文鏈接:https://www.uj5u.com/ruanti/326193.html
