我有以下類布局:
abstract class GenericClass<TArgs> where TArgs : ArgsBaseClass { }
abstract class ArgsBaseClass { }
class RandomArgs : ArgsBaseClass { }
class RandomClass : GenericClass<RandomArgs> { }
現在我希望能夠RandomClass從 的實體創建 的實體RandomArgs,而不知道它應該是RandomClass。即不知何故我需要推匯出RandomClass實作GenericClass<RandomArgs>.
我能夠創建一個GenericClass<RandomArgs>使用實體:
void CreateSpecificInstance(ArgsBaseClass args)
{
Type genericType = typeof(GenericClass<>).MakeGenericType(typeof(args));
var genericInstance = Activator.CreateInstance(genericType, typeof(args));
// But then I need help for the following step:
Type specificType = ... // in this case RandomClass, but should be derived from 'args'.
var specificInstance = (specificType)genericInstance;
}
任何幫助表示贊賞。
編輯:
基本上我有多個args班級。每個args類都有一個各自的“普通”類,可以用這個args類初始化。因此GenericClass<ArgsBaseClass>。
現在,每當我將 的實體傳遞ArgsBaseClass給某個函式(在我的名為CreateSpecificInstance.
根據我的評論,我想可以在每個args類和“普通”類之間創建映射,例如使用字典,但是每當您添加新的args “普通”類組合時,您還需要更新此字典。因此,我想這里應該使用使用反射的解決方案,但是我沒有看到使用反射的解決方案不會迭代程式集或命名空間中的所有類,因此我尋求幫助。
uj5u.com熱心網友回復:
回答這個問題最重要的是很多非常具體的細節,特別是你的實作。
所以,這個答案不是一個特定的解決方案,而是旨在描述一組解決方案,或者至少是解決方案的成分。
在此類問題中,您遇到的最困難的事情是介面和型別的動態發現。例如,您在編譯時不知道Args型別和GenericClass實作的完整串列。
如果你事先知道,那你就很幸運了。只需要加載一個Dictionary<Type, Type>與Args型別作為鍵和執行型別的值。
如果不這樣做,您還有一個額外的問題需要解決:如何唯一標識實作型別?也有很多方法可以解決這個問題,但它們涉及某種形式Assembly.GetTypes()或(更好)使用具有內置程式集掃描功能的良好 IoC 框架(我最喜歡Autofac)。您還需要解決如果發現相同 args 的兩個實作會發生什么的問題(可能只是原則上,但這是一個您需要回答的問題)。
回到我們的實作型別。我們有一個Args實體或型別,我們有我們的型別字典,所以我們找到了Type的正確實作GenericClass<TArgs>。現在您需要一種構建實體的方法。如果你能確保你有一個無引數的建構式,你可以呼叫Activator.CreateInstance(myGenericType). 這將為您提供一個RandomClass, 裝箱在object.
您需要以某種方式投射它才能使用它,也許是GenericClass<RandomArgs>.
如果您沒有無引數建構式,并且可以,請嘗試使用 IoC 容器來努力為您發現建構式依賴項。同樣,Autofac是一個不錯的候選人,但有很多選擇,這是一個很深的兔子洞。
所以,在最簡單的情況下,你只需要這樣的東西:
private Dictionary<Type, Type> _implementations =
new Dictionary<Type, Type>();
public void RegisterImplementation<TArgs, TImpl>()
where TArgs : ArgsBaseClass
where TImpl : GenericClass<TArgs>, new()
{
_implementations[typeof(TArgs)] = typeof(TImpl);
}
public GenericClass<TArgs> MakeClass<TArgs>(TArgs args) where TArgs : ArgsBaseClass
{
var implementationType = _implementations.TryGetValue(typeof(TArgs), out var t)
? t
: throw new ArgumentException("The args type " typeof(TArgs) " is unrecognized.", nameof(args));
return (GenericClass<TArgs>)Activator.CreateInstance(implementationType);
}
uj5u.com熱心網友回復:
我決定走另一條路,改用工廠方法模式。
轉載請註明出處,本文鏈接:https://www.uj5u.com/caozuo/375645.html
