我試圖弄清楚從泛型類中呼叫函式的最佳方法是什么。
public T Create<T>(T obj)
{
switch (obj.GetType().Name)
{
case "Bank":
(new Bank()).Create(obj);
break;
case "Bar":
(new Bar()).Create(obj);
break;
case "Beer":
(new Beer()).Create(obj);
break;
default:
(new Broke()).Create(obj);
break;
}
return obj;
}
我問了我的好朋友 Alexa、Siri 和 Google,但他們并沒有那么有幫助。通常,我能夠從其中一個人那里得到我需要的所有答案......
2天后
我當時解釋得不好。但我繼續使用巨型開關,簡化版本看起來像這樣。使用 CreateEntity 函式多載接受每個不同的類。
public Entry Create<T>(T obj, ObjBuilder builder)
{
Entry entry;
switch (obj)
{
case Profile p:
entry = builder.CreateEntity(p);
break;
case Area a:
entry = builder.CreateEntity(a);
break;
case Credential c:
entry = builder.CreateEntity(c);
break;
case Device d:
entry = builder.CreateEntity(d);
break;
}
return entry;
}
uj5u.com熱心網友回復:
我建議您考慮使用 aDictionary<Type, Delegate>來完成這項作業。它可能看起來很復雜,但它使您能夠在運行時添加任意數量的型別。
這是代碼:
private Dictionary<Type, Delegate> _creators = new Dictionary<Type, Delegate>();
public Entry Create<T>(T obj, ObjBuilder builder) =>
_creators.ContainsKey(typeof(T))
? ((Func<ObjBuilder, T, Entry>)_creators[typeof(T)])(builder, obj)
: null;
public void Register<T>(Func<ObjBuilder, T, Entry> factory)
{
_creators[typeof(T)] = factory;
}
現在只需注冊您的工廠:
Register<Profile>((b, x) => b.CreateEntity(x));
Register<Area>((b, x) => b.CreateEntity(x));
Register<Credential>((b, x) => b.CreateEntity(x));
Register<Device>((b, x) => b.CreateEntity(x));
簡單的。
或者您可以像這樣對字典進行硬編碼:
private Dictionary<Type, Delegate> _creators = new Dictionary<Type, Delegate>()
{
{ typeof(Profile), (Func<ObjBuilder, Profile, Entry>)((b, x) => b.CreateEntity(x)) },
{ typeof(Area), (Func<ObjBuilder, Area, Entry>)((b, x) => b.CreateEntity(x)) },
{ typeof(Credential), (Func<ObjBuilder, Credential, Entry>)((b, x) => b.CreateEntity(x)) },
{ typeof(Device), (Func<ObjBuilder, Device, Entry>)((b, x) => b.CreateEntity(x)) },
};
或者您可以將兩者結合使用。
這是使用您擁有的原始代碼執行此操作的方法:
void Main()
{
Register<Bank>(obj => (new Bank()).Create(obj));
Register<Bar>(obj => (new Bar()).Create(obj));
Register<Beer>(obj => (new Beer()).Create(obj));
Register<Broke>(obj => (new Broke()).Create(obj));
}
private Dictionary<Type, Delegate> _creators = new Dictionary<Type, Delegate>();
public T Create<T>(T obj)
{
if (_creators.ContainsKey(typeof(T)))
{
((Func<T, T>)_creators[typeof(T)])(obj);
}
return obj;
}
public void Register<T>(Action<T> action)
{
_creators[typeof(T)] = action;
}
uj5u.com熱心網友回復:
一個簡單的解決方案是讓所有物體實作相同的介面。
public interface ICreateable<T> {
T Create();
}
public class Bank : ICreateable<Bank> {
public Bank Create()
{
return new Bank();
}
// ...
}
雖然不太確定用例是什么。
uj5u.com熱心網友回復:
您可以嘗試通過以下方式解決問題嗎?
public class EntryData
{
int X { get; }
int Y { get; }
}
public interface IEntryData {
EntryData GetEntryData();
}
public class Profile: IEntryData {
...
public EntryData AsEntry();
}
public class Area: IEntryData {
...
public EntryData AsEntry();
}
...
Option 1:
public Entry Create(object obj, ObjBuilder builder) {
if(obj is not IEntryData) {...}
IEntryData entryData = obj as IEntryData;
builder.CreateEntity(entryData);
}
Option 2:
public Entry Create(IEntryData obj, ObjBuilder builder)
=> builder.CreateEntity(entryData);
...
class ObjBuilder {
Entry CreateEntity(IEntryData entryData) {
// Other things
var extra = ...
return new Entry(
x: entryData.X,
y: entryData.Y,
z: extra.Z)
}
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/494529.html
上一篇:C#如何在代碼中動態實體化型別
下一篇:類java的多個泛型型別
