如何利用泛型来填充派生类模型以避免代码重复?

ILo*_*low 12 c# generics

我有两种类型,每种类型都有不同的处理逻辑.根据该处理,我正在准备一个结果并将其返回给消费者(mvc应用程序,控制台应用程序等..)

  • 输入1
  • 类型2

现在问题是一些代码在两种类型中都很常见.唯一不同的部分是Type1Manager,Type2Manager两个类型的class(),它们实际上包含处理type1 and type2和准备结果的逻辑(Type1Model,Type2Model).

public class Variant
{
    public int Id { get; set; }
    public string Name { get; set; }
    public List<Subvariants> Subvariants { get; set; }
}

public class Subvariants
{
    public int Id { get; set; }
    public string Name { get; set; }
}

public abstract class BaseManager
{
    //Other shared code
    public abstract ExecutionResult GetExecutionResult(Variant model);
}

public class ExecutionResult
{
    public string Name { get; set; }
    public string ErrorMessage { get; set; }
    public bool Success { get; set; }
    public List<Type1Model> Types1 { get; set; }
    public List<Type2Model> Types2 { get; set; }
}

public abstract class BaseModel<T>
{
    public string Name { get; set; }
    public T Value { get; set; }
    public T Coordinates { get; set; }
    public decimal OverAllPercentage { get; set; }
}

public class Type1Model : BaseModel<int>
{
    public decimal MiscPercentage { get; set; }
    public int PerformanceCounter { get; set; }
}

public class Type2Model : BaseModel<decimal> { }

public class Type1 : BaseManager
{
    public override ExecutionResult GetExecutionResult(Variant model)
    {
        var executionResult = new ExecutionResult();
        executionResult.Name = model.Name;
        var type1Result = new List<Type1Model>();
        try
        {
            for (int counter = 0; counter < model.Subvariants.Count - 1; counter++)
            {
                var left = model.Subvariants[counter];
                var right = model.Subvariants[counter + 1];
                using (var t = new Type1Manager(model))
                {
                    for (int i = 0; i < 2; i++)
                    {
                        if (i == 0)
                        {
                            t.Start(i);
                            if (counter == 0)
                            {
                                type1Result.Add(new Type1Model
                                {
                                    Name = left.Name,
                                    Value = t.Left
                                });
                            }
                        }
                        else
                        {
                            t.Start(i);
                            type1Result.Add(new Type1Model
                            {
                                Name = right.Name,
                                Value = t.Right,
                                Coordinates = t.Left + t.Right,
                                OverAllPercentage = t.OverAllPercentage,
                                PerformanceCounter = (t.NetPlus + t.AverageRatio),
                                MiscPercentage = t.MiscPercentage
                            });
                        }
                    }
                }
            }
            executionResult.Types1 = type1Result;
        }
        catch (Exception ex)
        {
            executionResult.Success = false;
            executionResult.ErrorMessage = ex.Message;
        }
        return executionResult;
    }
}

internal class Type1Manager : IDisposable
{
    private Variant model;
    public int Right { get; private set; }
    public int Left { get; private set; }
    public int NetPlus { get; private set; }
    public int AverageRatio { get; private set; }
    public decimal OverAllPercentage { get; private set; }
    public decimal MiscPercentage { get; private set; }
    public Type1Manager(Variant model)
    {
        this.model = model;
    }

    public void Start(int i)
    {

    }

    public void Dispose()
    {
        throw new NotImplementedException();
    }
}

public class Type2 : BaseManager
{
    public override ExecutionResult GetExecutionResult(Variant model)
    {
        var executionResult = new ExecutionResult();
        executionResult.Name = model.Name;
        var type2Result = new List<Type2Model>();
        try
        {
            for (int counter = 0; counter < model.Subvariants.Count - 1; counter++)
            {
                var left = model.Subvariants[counter];
                var right = model.Subvariants[counter + 1];
                using (var t = new Type2Manager(model))
                {
                    for (int i = 0; i < 2; i++)
                    {
                        if (i == 0)
                        {
                            t.Start(i);
                            if (counter == 0)
                            {
                                type2Result.Add(new Type2Model
                                {
                                    Name = left.Name,
                                    Value = t.Left
                                });
                            }
                        }
                        else
                        {
                            t.Start(i);
                            type2Result.Add(new Type2Model
                            {
                                Name = right.Name,
                                Value = t.Right,
                                Coordinates = t.Left + t.Right,
                                OverAllPercentage = t.OverAllPercentage,
                            });
                        }
                    }
                }
            }
            executionResult.Types2 = type2Result;
        }
        catch (Exception ex)
        {
            executionResult.Success = false;
            executionResult.ErrorMessage = ex.Message;
        }
        return executionResult;
    }
}

internal class Type2Manager : IDisposable
{
    private Variant model;
    public decimal Right { get; private set; }
    public decimal Left { get; private set; }
    public decimal OverAllPercentage { get; private set; }
    public Type2Manager(Variant model)
    {
        this.model = model;
    }

    public void Start(int i)
    {

    }
    public void Dispose()
    {
        throw new NotImplementedException();
    }
}
Run Code Online (Sandbox Code Playgroud)

我面临的问题是那个Type1 needs Type1ModelType2 needs Type2Model.即使我尝试在我的BaseManager课程中移出常用代码,我将如何填充Type1Model and Type2Model模型?我正在努力的部分是重构两种类型的代码并在基类中移动一些常见的逻辑.

有可能重构两个类型的重复代码并在基类中移动它吗?

更新:

public abstract class BaseManager
 {
        public abstract ExecutionResult GetExecutionResult(Variant model);
        public abstract void ExecuteAndSave(Variant model, string connectionString);
 }




public class Type1 : BaseManager
    {
        public override void ExecuteAndSave(Variant model, string connectionString)
        {
            //other logic
            var t = new Type1Manager(new SaveData());
        }

        public override ExecutionResult GetExecutionResult(Variant model)
        {
            var executionResult = new ExecutionResult();
            executionResult.Name = model.Name;
            var type1Result = new List<Type1Model>();
            try
            {
                for (int counter = 0; counter < model.Subvariants.Count - 1; counter++)
                {
                    var left = model.Subvariants[counter];
                    var right = model.Subvariants[counter + 1];
                    using (var t = new Type1Manager(new Repository()))
                    {
                        for (int i = 0; i < 2; i++)
                        {
                            if (i == 0)
                            {
                                t.Start(null,null);
                                if (counter == 0)
                                {
                                    type1Result.Add(new Type1Model
                                    {
                                        Name = left.Name,
                                        Value = t.Left
                                    });
                                }
                            }
                            else
                            {
                                t.Start(null,null);
                                type1Result.Add(new Type1Model
                                {
                                    Name = right.Name,
                                    Value = t.Right,
                                    Coordinates = t.Left + t.Right,
                                    OverAllPercentage = t.OverAllPercentage,
                                    PerformanceCounter = (t.NetPlus + t.AverageRatio),
                                    MiscPercentage = t.MiscPercentage
                                });
                            }
                        }
                    }
                }
                executionResult.Types1 = type1Result;
            }
            catch (Exception ex)
            {
                executionResult.Success = false;
                executionResult.ErrorMessage = ex.Message;
            }
            return executionResult;
        }
    }

    internal class Type1Manager : IDisposable
    {
        public int Right { get; private set; }
        public int Left { get; private set; }
        public int NetPlus { get; private set; }
        public int AverageRatio { get; private set; }
        public decimal OverAllPercentage { get; private set; }
        public decimal MiscPercentage { get; private set; }
        private Repository _repository;
        public Type1Manager(Repository repository)
        {
            this._repository = repository;
        }

        public void Start(string connectionString,string sqlQuery)
        {

        }

        public void Dispose()
        {
            throw new NotImplementedException();
        }
    }

    public class Repository
    {
         //Dont save result here.Used only for Type1
    }

    public class SaveData : Repository
    {
        //Save result here.Used only for Type1
    }

    public class Type2 : BaseManager
    {
        public override void ExecuteAndSave(Variant model, string connectionString)
        {
            //using (var t = new Type2Manager(2)//not hardcoded.taken from model
        //Save data here returns from Type2Manager instance
        }

        public override ExecutionResult GetExecutionResult(Variant model)
        {
            var executionResult = new ExecutionResult();
            executionResult.Name = model.Name;
            var type2Result = new List<Type2Model>();
            try
            {
                for (int counter = 0; counter < model.Subvariants.Count - 1; counter++)
                {
                    var left = model.Subvariants[counter];
                    var right = model.Subvariants[counter + 1];
                    using (var t = new Type2Manager(2)) //not hardcoded.taken from model
                    {
                        for (int i = 0; i < 2; i++)
                        {
                            if (i == 0)
                            {
                                t.Start(null,null);
                                if (counter == 0)
                                {
                                    type2Result.Add(new Type2Model
                                    {
                                        Name = left.Name,
                                        Value = t.Left
                                    });
                                }
                            }
                            else
                            {
                                t.Start(null,null);
                                type2Result.Add(new Type2Model
                                {
                                    Name = right.Name,
                                    Value = t.Right,
                                    Coordinates = t.Left + t.Right,
                                    OverAllPercentage = t.OverAllPercentage,
                                });
                            }
                        }
                    }
                }
                executionResult.Types2 = type2Result;
            }
            catch (Exception ex)
            {
                executionResult.Success = false;
                executionResult.ErrorMessage = ex.Message;
            }
            return executionResult;
        }
    }

    internal class Type2Manager : IDisposable
    {
        public decimal Right { get; private set; }
        public decimal Left { get; private set; }
        public decimal OverAllPercentage { get; private set; }
        int precision;
        public Type2Manager(int precision)
        {
            this.precision = precision;
        }

        public void Start(string connectionString, string sqlQuery)
        {

        }
        public void Dispose()
        {
            throw new NotImplementedException();
        }
    }
Run Code Online (Sandbox Code Playgroud)
  • 变种:地区
  • 子变量:SubRegion
  • Type1:AnalyticalCalculator
  • Type2:AggregateCalculator

Mar*_*kus 2

如果您使基类通用并设置正确的约束,则可以将大部分代码提取到基类中。此外,您需要为每种类型创建特定的实现。
以下示例应该可以让您有所了解:

public abstract class SharedLogicClass<TValue, TType>
  where TType : BaseModel<TValue>, new
{
    public override ExecutionResult GetExecutionResult(Variant model)
    {
      var executionResult = new ExecutionResult();
      executionResult.Name = model.Name;
      var type1Result = new List<TTYpe>();
      try
      {
        for (int counter = 0; counter < model.Subvariants.Count - 1; counter++) 
        {
          var left = model.Subvariants.Count[counter];
          var right = model.Subvariants.Count[counter + 1];
          using (var t = CreateTypeManager(model))
          {
            for (int i = 0; i < 2; i++)
            {
              if (i == 0)
              {
                t.Start(i);
                if (counter == 0)
                {
                  type1Result.Add(new TType()
                  {
                    Name = left.Name,
                    Value = t.LeftValue
                  });
                }
              }
              else
              {
                t.Start(i);
                var type = new TType()
                {
                  Name = right.Name,
                  Value = t.RightValue,
                  Coordinates = t.Left + t.Right,
                  OverAllPercentage = t.OverAllPercentage,
                });
                AssignAdditionalValues(type, t);
                type1Result.Add(type);
              }
            }
          }
        }
        AssignExecutionResult(executionResult, type1Result);
      }
      catch (Exception ex)
      {
        executionResult.Success = false;
        executionResult.ErrorMessage = ex.Message;
      }
      return executionResult;
    }
    protected abstract BaseManager CreateTypeManager(Variant model);
    protected virtual void AssignAdditionalData(Type1Model type, TypeManager t) {}
    protected abstract void AssignExecutionResultList(ExecutionResult res, IList<TType> lst);
}

public class SharedLogicImplementationType1 : SharedLogicClass<int, Type1Model>
{
  protected override BaseManager CreateTypeManager(Variant model)
  {
    return new Type1Manager(model);
  }

  protected override void AssignAdditionalData(Type1Model type, TypeManager t)
  {
    type.PerformanceCounter = (t.NetPlus + t.AverageRatio);
    type.MiscPercentage = t.MiscPercentage;
  }

  protected override void AssignExecutionResultList(ExecutionResult res, IList<Type1Model> lst)
  {
    res.Types1 = lst;
  }
}


public class SharedLogicImplementationType2 : SharedLogicClass<decimal, Type2Model>
{
  protected override BaseManager CreateTypeManager(Variant model)
  {
    return new Type2Manager(model);
  }

  protected override void AssignExecutionResultList(ExecutionResult res, IList<Type2Model> lst)
  {
    res.Types2 = lst;
  }
}
Run Code Online (Sandbox Code Playgroud)

请将代码视为示例,而不是完成的作品。