gpt4 book ai didi

c# - 重构以避免重复代码

转载 作者:太空宇宙 更新时间:2023-11-03 14:24:23 25 4
gpt4 key购买 nike

我试图分解出一些重复的代码,但现在开始闻起来很奇怪了。假设我一开始不太正确,但你明白我的意思:

    public virtual OrganisationEntity Get(int id)
{
SqlCommand command = new SqlCommand();
command.CommandText = @"SELECT t.Id, t.Description FROM Organisation t Where t.Id = @Id";
command.Parameters.Add("@id", SqlDbType.Int).Value = id;

List<OrganisationEntity> entities = new List<OrganisationEntity>();

SqlDataReader reader = Database.ExecuteQuery(command, ConnectionName.Dev);

while (reader.Read())
{
OrganisationEntityMapper mapper = Mapper;
entities = mapper.MapAll(reader);
}

return entities.First<OrganisationEntity>();
}

很明显,除了查询之外,其他所有 Get(int id) 方法都具有相同的形式,因此我的下一步是制作一个基类,RepositoryBase 如下所示:

public abstract class RepositoryBase<T> where T : new()
{
/// <summary>
///
/// </summary>
public abstract EntityMapperBase<T> Mapper { get; }

public virtual T Get(int id)
{

List<T> entities = new List<T>();

SqlDataReader reader = Database.ExecuteQuery(Command, ConnectionName);

while (reader.Read())
{
EntityMapperBase<T> mapper = Mapper;
entities = mapper.MapAll(reader);
}

return entities.First<T>();
}
}

添加一些通用的时髦元素,但这也是它变得丑陋的地方。首先,Database.ExecuteQuery 需要一个 SqlCommand 和一个枚举,所以我想,好吧,然后我会添加 2 个属性,我会用一些东西来启动它们。然后我意识到我不再需要这里的 int id 参数,因为我在子类中构造了查询,所以我不妨将命令和 connectionName 作为参数传递,我希望 connectionName 无论如何都是 OrganisationRepository 的依赖项(其他需要另一个字符串):

public class OrganisationRepository : RepositoryBase<OrganisationEntity>
{
protected override EntityMapperBase<OrganisationEntity> Mapper
{
get
{
return new OrganisationMapper();
}
}

public override OrganisationEntity Get(int id)
{
SqlCommand command = new SqlCommand();
command.CommandText = @"SELECT t.Id, t.Description FROM Organisation t Where t.Id = @Id";
command.Parameters.Add("@id", SqlDbType.Int).Value = id;
return base.Get(command, ConnectionName.Dev);
}
}

但是,哎呀,当然,现在方法签名不再同步了……哎呀!所以,基本上我想知道。只是感觉很恶心,但不知道为什么。一方面,我想尽可能多地排除重复代码,但现在我只剩下这个了!

我如何将其重构为(更)合适的 OO?我是否应该忘记分解查询字符串并写很多重复项?

最佳答案

你的“下一步”不会和我的一样。

我的下一步是找到您要重构的这个“通用代码”的另一个示例。也许是“`CustomerEntity.Get(int id)'”方法。

现在,让我们假设 CustomerEntity 和 OrganisationEntity 版本之间的唯一区别是查询字符串和将术语“Organisation”替换为“Customer”。我的下一步是尝试使这两种方法越来越一致。假设此方法是 OrganisationEntityRepository 类的一部分,我会将其重构为 EntityRepository1 类,并将 CustomerEntityRepository 重构为 EntityRepository2。

第 1 步是为实体类型引入通用参数。您必须对 OrganisationEntityMapper 和 CustomerEntityMapper 类执行相同的操作。

接下来,回过头来看看还有什么不同。我看到他们使用不同的映射器类,所以让我们使映射器类型通用。为了做到这一点并仍然引用 MapAll 方法,我将引入一个带有 MapAll 方法的 IMapper 接口(interface),并让我的两个具体映射器类实现它。

现在,下一个很大的区别是查询。我会将其放入虚拟的“CommandText”属性中。

现在我想我已经准备好学习基础类(class)了,也许是EntityRepositoryBase<TEntity,TMapper> .通过适当的假设,我得出以下结论:

public abstract class EntityRepositoryBase<TEntity, TMapper>
where TMapper : IMapper<TEntity>
{
public virtual TEntity Get(int id)
{
List<TEntity> entities;
using (var command = new SqlCommand {CommandText = CommandText})
{
command.Parameters.Add("@id", SqlDbType.Int).Value = id;

entities = new List<TEntity>();

using (var reader = Database.ExecuteQuery(command, ConnectionName.Dev))
{
while (reader.Read())
{
var mapper = Mapper;
entities = mapper.MapAll(reader);
}
}
}

return entities.First();
}

protected abstract string CommandText { get; }
protected abstract TMapper Mapper { get; }
}

public class OrganisationEntityRepository :
EntityRepositoryBase<OrganisationEntity, OrganisationEntityMapper<OrganisationEntity>>
{
protected override string CommandText
{
get { return @"SELECT t.Id, t.Description FROM Organisation t Where t.Id = @Id"; }
}

protected override OrganisationEntityMapper<OrganisationEntity> Mapper
{
get { throw new NotImplementedException(); }
}
}

public class CustomerEntityRepository : EntityRepositoryBase<CustomerEntity, CustomerEntityMapper<CustomerEntity>>
{
protected override string CommandText
{
get { return @"SELECT t.Id, t.Description FROM Customer t Where t.Id = @Id"; }
}

protected override CustomerEntityMapper<CustomerEntity> Mapper
{
get { throw new NotImplementedException(); }
}
}

而且,不用说,尽管我还是要说:支持 JetBrains ReSharper 5.1 进行所有移动,所以我不必这样做。

关于c# - 重构以避免重复代码,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4453746/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com