【问题标题】:Troubles with large amount of Code duplication大量重复代码的问题
【发布时间】:2014-12-04 19:49:47
【问题描述】:

我有很多方法在很大程度上遵循相同的算法,理想情况下,我希望能够调用通用方法,从而消除大量代码重复。

我有很多像下面这样的方法,我希望能够只调用 Save<SQLiteLocation>(itemToSave); 但我遇到了很多麻烦,因为这些方法 SQLiteConnection.Find<T> 在泛型中不接受像 T 这样的抽象数据类型。

有什么办法可以解决这个问题,如果我能修复它,我会节省多达 150 行代码

这是我的代码:

    public bool SaveLocation(ILocation location, ref int primaryKey)
    {
        var dbConn = new SQLiteConnection (dbPath);

        SQLiteLocation itemToSave = new SQLiteLocation ();
        itemToSave.LocationName = location.LocationName;
        itemToSave.Latitude = location.Latitude;
        itemToSave.Longitude = location.Longitude;
        itemToSave.PrimaryKey = location.PrimaryKey;

  ----------------------------------------------------------------------------------------

        SQLiteLocation storedLocation = dbConn.Find<SQLiteLocation>
                                        (x => x.PrimaryKey == location.PrimaryKey);

        if (storedLocation != null)
        {
            dbConn.Update(itemToSave);
            return true;
        }

        else if (storedLocation == null)
        {
            dbConn.Insert(itemToSave);
            primaryKey = itemToSave.PrimaryKey;
            return true;
        }
        return false;
    }

这里还有另一种方法,看看我的虚线下面的两种方法中的代码基本上是一样的

    public bool SaveInvitation(IInvitation invitation, ref int primaryKey)
    {
        var dbConn = new SQLiteConnection(dbPath);

        SQLiteInvitation itemToSave = new SQLiteInvitation ();
        itemToSave.GroupName = invitation.GroupName;
        itemToSave.InviterName = invitation.InviterName;
        itemToSave.ParseID = invitation.ParseID;
        itemToSave.GroupParseID = invitation.GroupParseID;
        itemToSave.PrimaryKey = invitation.PrimaryKey;

---------------------------------------------------------------------------------------

        SQLiteInvitation storedInvitation = dbConn.Find<SQLiteInvitation> 
                                            (x => x.PrimaryKey == invitation.PrimaryKey);

        if (storedInvitation != null)
        {
            dbConn.Update(itemToSave);
            return true;
        }
        else if (storedInvitation == null)
        {
            dbConn.Insert(itemToSave);
            primaryKey = itemToSave.PrimaryKey;
            return true;
        }
        return false;
    }

【问题讨论】:

  • 您可以使用 AutoMapper 或类似的东西来移动属性。另外,如果您将itemToSave 移出方法并将其作为参数传递,那么我相信您可以使其余代码通用。
  • 您是否考虑过研究表达式树来构建Find&lt;T&gt; 语句?
  • storedX 要么是null,要么不是,所以不需要使用else if。因此,您永远不会返回 false,因此您可以删除返回值。左边是if(storedX != null){ dbConn.Update(itemToSave); } else{ dbConn.Insert(itemToSave); primaryKey = itemToSave.PrimaryKey; }。在那里删除了 3 行
  • 我会研究 AutoMapper 和 Expression 树,虽然我不熟悉它,但我会研究它,谢谢您的输入。是的,你是对的,它总是为空或不为空,谢谢

标签: c# generics android-sqlite maintainability


【解决方案1】:

难道你不能做这样的事情: 注意:ICommonInterface 是您希望用作 T 的任何允许的类之间共有的任何东西。最好查看您的代码、公开 PrimaryKey 属性的接口或类。

public bool SaveItem<T>(T item, ref int primaryKey) where T : ICommonInterface, new()
{
    var dbConn = new SQLiteConnection(dbPath);


    T storedItem = dbConn.Find<T>(x => x.PrimaryKey == item.PrimaryKey);

    if (storedItem != null)
    {
        dbConn.Update(item);
        return true;
    }
    else if (storedItem == null)
    {
        dbConn.Insert(item);
        primaryKey = item.PrimaryKey;
        return true;
    }
    return false;
}

编辑:在方法中添加了 new() 约束。

【讨论】:

  • 你是对的,这修复了我的代码,你保存了我的很多行代码
  • 实际上我似乎太鲁莽了,我得到这个错误:'T'必须是具有公共无参数构造函数的非抽象类型才能将其用作泛型类型中的参数'T'或方法 'SQLite.SQLiteConnection.Find(System.Linq.Expressions.Expression>)' (CS0310) (ShoppingAssistant)
  • 查看修改后的答案。向该方法添加一个 new() 约束。例如:其中 T : ICommonInterface, new()
【解决方案2】:

由于某种原因,它抛出了一个不受支持的异常 我用的时候:

    T storedItem = dbConn.Find<T>(x => x.PrimaryKey == item.PrimaryKey);

下面的代码解决了我的问题,感谢大家的帮助,我喜欢这个网站! 此外,我在 T 上添加了另一个约束,因为 T 必须是非抽象类型,而接口正是我想的那样

    private void SaveItem<T>(T item, ref int primaryKey) 
        where T : ISQLiteClass, new()
    {
        var dbConn = new SQLiteConnection(dbPath);

        T storedItem = dbConn.Find<T>(primaryKey);

        if (storedItem != null)
        {
            dbConn.Update(item);
        }
        else if (storedItem == null)
        {
            dbConn.Insert(item);
            primaryKey = item.PrimaryKey;
        }
    }

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-06-05
    • 2016-06-08
    • 2020-07-28
    • 2010-12-01
    • 1970-01-01
    相关资源
    最近更新 更多