C# 保持方法干燥,每种方法略有不同

C# 保持方法干燥,每种方法略有不同,c#,dry,C#,Dry,我正在编写一个转换类,用于在提取API数据时使用的模型之间进行转换,并使用实体框架进行模型转换。这两者分开的原因是由于字段上的JSON.Net注释,从api中提取数据以及将其与entitfy framework&asp.Net一起使用时,我需要的注释之间存在冲突 除了一个字段外,我有十几个几乎相同的so类。下面是两种转换方法的示例 public static IEnumerable<PlayerUnitsKilledRank> ConvertPlayerUnitsKilledRank

我正在编写一个转换类,用于在提取API数据时使用的模型之间进行转换,并使用实体框架进行模型转换。这两者分开的原因是由于字段上的JSON.Net注释,从api中提取数据以及将其与entitfy framework&asp.Net一起使用时,我需要的注释之间存在冲突

除了一个字段外,我有十几个几乎相同的so类。下面是两种转换方法的示例

public static IEnumerable<PlayerUnitsKilledRank> ConvertPlayerUnitsKilledRankings(IEnumerable<ApiCombatUnitsKilledRank> rankings, int world)
{
    List<PlayerUnitsKilledRank> dbRankings = new List<PlayerUnitsKilledRank>();
    DateTime now = DateTime.Now.Date;
    foreach (ApiCombatUnitsKilledRank rank in rankings)
    {
        PlayerUnitsKilledRank dbRank = new PlayerUnitsKilledRank()
        {
            Date = now,
            World = world,
            Player = rank.Player,
            Alliance = rank.Alliance,
            Rank = rank.Rank,
            UnitsKilled = rank.UnitsKilled
        };
        dbRankings.Add(dbRank);
    }
    return dbRankings;
}

public static IEnumerable<PlayerCavernRaidingRank> ConvertPlayerCavernRaidingRankings(IEnumerable<ApiRaidingCavernRank> rankings, int world)
{
    List<PlayerCavernRaidingRank> dbRankings = new List<PlayerCavernRaidingRank>();
    DateTime now = DateTime.Now.Date;
    foreach (ApiRaidingCavernRank rank in rankings)
    {
        PlayerCavernRaidingRank dbRank = new PlayerCavernRaidingRank()
        {
            Date = now,
            World = world,
            Player = rank.Player,
            Alliance = rank.Alliance,
            Rank = rank.Rank,
            Plundered = rank.ResourcesPlundered
        };
        dbRankings.Add(dbRank);
    }
    return dbRankings;
}
public静态IEnumerable converterplayernitskilledrankings(IEnumerable排名,int world)
{
List dbRankings=新列表();
DateTime now=DateTime.now.Date;
foreach(排名中排名靠前)
{
playernitskilledebrank=新的playernitskilledebed()
{
日期=现在,
世界=世界,
玩家=等级。玩家,
联盟=等级联盟,
秩=秩,秩,
UnitsKilled=rank.UnitsKilled
};
添加(dbRank);
}
返回排名;
}
公共静态IEnumerable ConverterPlayerAverRaidingRangings(IEnumerable排名,国际排名)
{
List dbRankings=新列表();
DateTime now=DateTime.now.Date;
foreach(排名中的排名)
{
PlayerCavernRaidingRank dbRank=新的PlayerCavernRaidingRank()
{
日期=现在,
世界=世界,
玩家=等级。玩家,
联盟=等级联盟,
秩=秩,秩,
掠夺的,掠夺的
};
添加(dbRank);
}
返回排名;
}
你怎样才能消除多余的代码,保持我的类的干燥?这些方法彼此非常相似,但我想不出一个好办法来做到这一点


我可以使用泛型方法,但我仍然有一个单独的属性需要处理。由于每个类都非常相似,我可以创建一个它们都从中继承的基类,但一次性属性仍然是一个问题。

提取
ApicomBatUnitsKilledEngalledEngalledEngalledEngalledEngalledEngade
ApiraidingCanveRank
之间的公共接口。此接口可以有一个方法:
IRank ProduceRank()

PlayerCavernRaidingRank
playerUnitSkille
应继承相同的
IRank
接口

您所指的“一次性属性”现在是一个具体的实现问题,您实际上可以拥有任意数量的此类属性

public interface IRank
{
    // Your common rank properties here
    // Maybe even create a base abstract Rank class ...
}

public interface IRankProducer
{
    IRank ProduceRank();
}

public class PlayerCavernRaidingRank : IRank
{
}

public class PlayerUnitsKilledRank : IRank
{
}

public class ApiCombatUnitsKilledRank : IRankProducer
{
    public IRank ProduceRank()
    {
        return new PlayerUnitsKilledRank()
        {
            Player = this.Player,
            Alliance = this.Alliance,
            Rank = this.Rank,
            UnitsKilled = this.UnitsKilled
        };
    }
}

public class ApiRaidingCavernRank : IRankProducer
{
    public IRank ProduceRank()
    {
        return new PlayerCavernRaidingRank()
        {
            Player = this.Player,
            Alliance = this.Alliance,
            Rank = this.Rank,
            Plundered = this.ResourcesPlundered
        };
    }
}

public static IEnumerable<IRank> Convert(IEnumerable<IRankProducer> rankings, int world)
{
    var dbRankings = new List<IRank>();
    DateTime now = DateTime.Now.Date;
    foreach (IRankProducer rank in rankings)
    {
        var rank = rank.ProduceRank();
        rank.World = world;
        rank.Date = now;
        dbRankings.Add(rank);
    }

    return dbRankings;
}
公共接口入侵
{
//这里是您的公共秩属性
//甚至可能创建一个基础抽象等级类。。。
}
公共接口IRankProducer
{
IRank ProduceRank();
}
公共类玩家Averraidingrank:IRank
{
}
公开课剧作家尼茨基:伊朗
{
}
公共课:伊朗制片人
{
公共伊朗生产等级()
{
返回新的playernitskilleed()
{
Player=这个,Player,
联盟=这个,联盟,
秩=这个,秩,
UnitsKilled=this.UnitsKilled
};
}
}
公共级别:IRankProducer
{
公共伊朗生产等级()
{
返回新的PlayerCavernRaidingRank()
{
Player=这个,Player,
联盟=这个,联盟,
秩=这个,秩,
掠夺的,掠夺的
};
}
}
公共静态IEnumerable转换(IEnumerable排名,int世界)
{
var dbRankings=新列表();
DateTime now=DateTime.now.Date;
foreach(伊朗生产商排名)
{
var rank=rank.ProduceRank();
世界=世界;
rank.Date=现在;
添加(排名);
}
返回排名;
}

提取
apicombatunitskillead
apiraidingcolvenrank
之间的公共接口。此接口可以有一个方法:
IRank ProduceRank()

PlayerCavernRaidingRank
playerUnitSkille
应继承相同的
IRank
接口

您所指的“一次性属性”现在是一个具体的实现问题,您实际上可以拥有任意数量的此类属性

public interface IRank
{
    // Your common rank properties here
    // Maybe even create a base abstract Rank class ...
}

public interface IRankProducer
{
    IRank ProduceRank();
}

public class PlayerCavernRaidingRank : IRank
{
}

public class PlayerUnitsKilledRank : IRank
{
}

public class ApiCombatUnitsKilledRank : IRankProducer
{
    public IRank ProduceRank()
    {
        return new PlayerUnitsKilledRank()
        {
            Player = this.Player,
            Alliance = this.Alliance,
            Rank = this.Rank,
            UnitsKilled = this.UnitsKilled
        };
    }
}

public class ApiRaidingCavernRank : IRankProducer
{
    public IRank ProduceRank()
    {
        return new PlayerCavernRaidingRank()
        {
            Player = this.Player,
            Alliance = this.Alliance,
            Rank = this.Rank,
            Plundered = this.ResourcesPlundered
        };
    }
}

public static IEnumerable<IRank> Convert(IEnumerable<IRankProducer> rankings, int world)
{
    var dbRankings = new List<IRank>();
    DateTime now = DateTime.Now.Date;
    foreach (IRankProducer rank in rankings)
    {
        var rank = rank.ProduceRank();
        rank.World = world;
        rank.Date = now;
        dbRankings.Add(rank);
    }

    return dbRankings;
}
公共接口入侵
{
//这里是您的公共秩属性
//甚至可能创建一个基础抽象等级类。。。
}
公共接口IRankProducer
{
IRank ProduceRank();
}
公共类玩家Averraidingrank:IRank
{
}
公开课剧作家尼茨基:伊朗
{
}
公共课:伊朗制片人
{
公共伊朗生产等级()
{
返回新的playernitskilleed()
{
Player=这个,Player,
联盟=这个,联盟,
秩=这个,秩,
UnitsKilled=this.UnitsKilled
};
}
}
公共级别:IRankProducer
{
公共伊朗生产等级()
{
返回新的PlayerCavernRaidingRank()
{
Player=这个,Player,
联盟=这个,联盟,
秩=这个,秩,
掠夺的,掠夺的
};
}
}
公共静态IEnumerable转换(IEnumerable排名,int世界)
{
var dbRankings=新列表();
DateTime now=DateTime.now.Date;
foreach(伊朗生产商排名)
{
var rank=rank.ProduceRank();
世界=世界;
rank.Date=现在;
添加(排名);
}
返回排名;
}

您可以将委托传递给泛型方法以解决此问题,或者如果所有
playrerak
都具有无参数构造函数,则可以使用
new()
约束

public static IEnumerable<TPlayerRank> ConvertRankings<TApiRank,TPlayerRank>(IEnumerable<TApiRank> rankings, int world/*, Func<TPlayerRank> func*/) 
    where TApiRank : APIRank, 
    where TPlayerRank : PlayerRank, new()
{
    List<TPlayerRank> dbRankings = new List<TPlayerRank>();
    DateTime now = DateTime.Now.Date;
    foreach (var rank in rankings)
    {
        //TPlayerRank dbRank = func();
        var dbRank = new TPlayerRank();

        dbRank.Date = now,
        dbRank.World = world,
        dbRank.Player = rank.Player,
        dbRank.Alliance = rank.Alliance,
        dbRank.Rank = rank.Rank,
        dbRank.Plundered = rank.ResourcesPlundered

        dbRankings.Add(dbRank);
    }
    return dbRankings;
}
公共静态IEnumerable排名(IEnumerable排名,int-world/*,Func-Func*/)
其中TApiRank:APIRank,
其中TPlayerRank:PlayerRank,new()
{
清单d