重构两个类似的方法将数据加载到不同的类

时间:2017-02-15 15:34:47

标签: c#

下面是两个示例方法,除了2类引用之外,两者都非常相似。即。一个使用FishSettings和FishTileData其他WallSettings和WallTileData。

如何编写单个方法然后调用/引用它所调用的类?我需要一个通用方法吗?

void Fish(int id, GameObject tile, TileType tileType)
    {
        FishSettings settings = tile.GetComponent<FishSettings>();
        foreach (FishTileData data in DataBase(tileType))
        {
            if (data.Id == id)
            {
                settings.Load(data);
                break;
            }
        }
    }
void Wall(int id, GameObject tile, TileType tileType)
    { 
        WallSettings settings = tile.GetComponent<WallSettings>();
        foreach (WallTileData data in DataBase(tileType))
        {
            if (data.Id == id)
            {
                settings.Load(data);
                break;
            }
        }
    }

void LoadData(GameObject _newTile, TileData _td)
{
    switch (_td.GetTileType())  // This is a virtual Method in the base class : TileData
    {
        case TileType.Fish:
            FishSettings settings = _newTile.GetComponent<FishSettings>();
            settings.Load((FishTileData)_td);
            break;
        case TileType.Wall:
            WallSettings settings = _newTile.GetComponent<WallSettings>();
            settings.Load((WallTileData)_td);
            break;
        default:
            break;
    }                
}

2 个答案:

答案 0 :(得分:0)

是的,您可以将这两个方法合并为一个通用方法,假设您可以修改所有其他涉及的类来实现某些接口。您需要创建具有相同名称(IdLoad)的方法,以便从约束到接口的泛型参数调用(假设类型没有您可以控制的公共父级)。

interface IHasId { int Id {get;}}
interface ILoadable<TData> { void Load(TData data);}

void LoadItem<TSettings, TData>(int id, GameObject tile, TileType tileType) 
       where : TSettings : ILoadable<TData>, TData : IHasId
{ 
    TSettings  settings = tile.GetComponent<TSettings>();
    foreach (TData data in DataBase(tileType))
    {
        if (data.Id = id)
        {
            settings.Load(data);
            break;
        }
    }
}

class WallSettings : ILoadable<WallTileData>, ...
class WallTileData : IHasId,...

并像

一样使用它
LoadItem<WallSettings, WallTileData>(...);

注意:

  • 搜索所有对象以按ID查找项目看起来很慢。您可能希望在DataBase
  • 中提供ID查找
  • 如果符合您的效果目标
  • ,您可以尝试使用dynamic代替泛型
  • 重写整体加载顺序以根据存储数据创建对象可能是更好的选择。

答案 1 :(得分:-2)

这看起来乍一看它可能是抽象基类中虚方法的候选者。

public abstract class GameObject 
{
    public virtual void LoadSettings(int id)
    {
        var tileType =
            this is Fish? TileType.Fish:
            this is Wall? TileType.Wall: TypeType.Null;
        var settings = 
            this is Fish? tile.GetComponent<FishSettings>():
            this is Wall? tile.GetComponent<WallSettings>():
                          null;

        foreach (var data in DataBase(tileType))
        {
            if (data.Id = id)
            {
                settings.Load(data);
                break;
            }
        }
    }
}
public class Fish: GameComponent
{
    // rest of Fish class
}
public class Wall: GameComponent
{
    // rest of Wall class
}