C#泛型重构

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>:-(

任何人都可以看到这可以很好地重构?

提前致谢

罗素

Blu*_*kMN 2

尝试使用模板化函数。它应该根据您传递的参数类型推断类型,因此您不需要在 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)