Rus*_*ngs 6 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();
}
}
Run Code Online (Sandbox Code Playgroud)
这个类的参考代码在这里......
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; }
}
Run Code Online (Sandbox Code Playgroud)
我的第一次尝试是像这样重构......
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);
}
}
Run Code Online (Sandbox Code Playgroud)
这个问题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);
}
}
Run Code Online (Sandbox Code Playgroud)
尝试#2:棘手的问题我认为您需要一个更通用的 IHelper 界面。这样的事情会有帮助吗?
public interface IHelper
{
IMyObj GetBasic();
IMyObj GetExisting();
}
public interface IHelper<T> : IHelper
{
T GetBasic();
T GetExisting();
}
Run Code Online (Sandbox Code Playgroud)
您必须解决派生接口和基接口之间的名称冲突,但我不确定您到底想如何做到这一点,而且我的时间不多了,所以我将保留它就目前而言。
尝试#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);
}
Run Code Online (Sandbox Code Playgroud)