[英]C# Generics Refactoring
我試圖重構一段似乎很容易重構的代碼,但事實證明很難。 有兩種方法看起來非常相似,我覺得應該重構: -
public class MyClass
{
private void AddBasicData(Receiver receiver)
{
var aHelper = new AHelper();
var bHelper = new BHelper();
var cHelper = new CHelper();
receiver.ObjA = aHelper.GetBasic();
receiver.ObjB = bHelper.GetBasic();
receiver.ObjC = cHelper.GetBasic();
}
private void AddExistingData(Receiver receiver)
{
var aHelper = new AHelper();
var bHelper = new BHelper();
var cHelper = new CHelper();
receiver.ObjA = aHelper.GetExisting();
receiver.ObjB = bHelper.GetExisting();
receiver.ObjC = cHelper.GetExisting();
}
}
這個類的參考代碼在這里......
public class AHelper : Helper<A>
{
}
public class BHelper : Helper<B>
{
}
public class CHelper : Helper<C>
{
}
public class Helper<T> : IHelper<T> where T : IMyObj
{
public T GetBasic()
{
...
}
public T GetExisting()
{
...
}
}
public interface IHelper<T>
{
T GetBasic();
T GetExisting();
}
public class A : IMyObj {}
public class B : IMyObj {}
public class C : IMyObj {}
public interface IMyObj {}
public class Receiver
{
public A ObjA { get; set; }
public B ObjB { get; set; }
public C ObjC { get; set; }
}
我的第一次嘗試是像這樣重構......
public class MyClass
{
private void AddBasicData(Receiver receiver)
{
Func<Helper<IMyObj>, IMyObj> func = x => x.GetBasic();
AddData(receiver, func);
}
private void AddExistingData(Receiver receiver)
{
Func<Helper<IMyObj>, IMyObj> func = x => x.GetExisting();
AddData(receiver, func);
}
private void AddData(Receiver receiver, Func<Helper<IMyObj>, IMyObj> func)
{
var aHelper = new AHelper();
var bHelper = new BHelper();
var cHelper = new CHelper();
receiver.ObjA = func(aHelper);
receiver.ObjB = func(bHelper);
receiver.ObjC = func(cHelper);
}
}
這個問題是new AHelper()
不能分配給Helper<IMyObj>
:-(
任何人都可以看到這可以很好地重構?
提前致謝
羅素
嘗試使用模板化功能。 它應該根據您傳遞的參數類型推斷類型,因此您不需要在AddData調用中顯式指定類型。
public class MyClass
{
private void AddData<T>(Receiver receiver, Func<Helper<T>, T> func)
{
var aHelper = new AHelper();
var bHelper = new BHelper();
var cHelper = new CHelper();
receiver.ObjA = func(aHelper);
receiver.ObjB = func(bHelper);
receiver.ObjC = func(cHelper);
}
}
嘗試#2:棘手的問題我認為你需要一個更通用的IHelper接口。 這樣的事情有幫助嗎?
public interface IHelper
{
IMyObj GetBasic();
IMyObj GetExisting();
}
public interface IHelper<T> : IHelper
{
T GetBasic();
T GetExisting();
}
你必須弄清楚派生界面和基礎界面之間的名稱沖突,但我不確定你是怎么想這樣做的,而且我已經沒時間了,所以我會留下那個就目前而言。
嘗試#3(我決心得到這個!):這會是作弊嗎?
public enum RetrievalMethod
{
Basic,
Existing
}
public class Helper<T> : IHelper<T> where T : IMyObj
{
public T Get(RetrievalMethod rm)
{
switch(rm)
{
case RetrievalMethod.Basic:
return GetBasic();
case RetrievalMethod.Existing:
return GetExisting();
}
}
...
}
...
private void AddData(Receiver receiver, RetrievalMethod rm)
{
var aHelper = new AHelper();
var bHelper = new BHelper();
var cHelper = new CHelper();
receiver.ObjA = aHelper.Get(rm);
receiver.ObjB = bHelper.Get(rm);
receiver.ObjC = cHelper.Get(rm);
}
您可以使用強制轉換來解決分配問題。 如果AHelper實際上返回A,我認為這是有效的
private void AddData(Receiver receiver, Func<Helper<IMyObj>, IMyObj> func)
{
var aHelper = new AHelper();
var bHelper = new BHelper();
var cHelper = new CHelper();
receiver.ObjA = (A) func(aHelper);
receiver.ObjB = (B) func(bHelper);
receiver.ObjC = (C) func(cHelper);
}
如果你重寫方法,你可以做轉換,不需要改變“Func,IMyObj>”的定義
public class AHelper : Helper<A>
{
public override A GetBasic()
{
return new A();
}
}
那這個呢?
private static T GetData<T, THelper>(Func<THelper, T> func)
where THelper : Helper<T>, new()
where T : IMyObj
{ return func(new THelper()); }
private static T GetBasicData<T, THelper>()
where THelper : Helper<T>, new()
where T : IMyObj
{ return GetData(x => x.GetBasic()); }
private static T GetExistingData<T, THelper>()
where THelper : Helper<T>, new()
where T : IMyObj
{ return GetData(x => x.GetExisting()); }
private void AddBasicData(Receiver receiver)
{
receiver.ObjA = GetBasicData<A, AHelper>();
receiver.ObjB = GetBasicData<B, BHelper>();
receiver.ObjC = GetBasicData<C, CHelper>();
}
private void AddExistingData(Receiver receiver)
{
receiver.ObjA = GetExistingData<A, AHelper>();
receiver.ObjB = GetExistingData<B, BHelper>();
receiver.ObjC = GetExistingData<C, CHelper>();
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.