干净代码:可读的依赖注入建议? - c#

我有一个项目,将元素添加到AutoCad绘图中。我注意到我开始用多种方法编写相同的十行代码(为简单起见仅显示两行)。

初步实施:
您会注意到,唯一真正改变的是添加一条线而不是一个圆。

[CommandMethod("Test", CommandFlags.Session)]
    public void Test()
    {
        AddLineToDrawing();
        AddCircleToDrawing();
    }

    private void AddLineToDrawing()
    {
        using (DocumentLock lockedDocument = Application.DocumentManager.MdiActiveDocument.LockDocument())
        {
            using (Database database = Application.DocumentManager.MdiActiveDocument.Database)
            {
                using (Transaction transaction = database.TransactionManager.StartTransaction())//Start the transaction
                {
                    //Open the block table for read
                    BlockTable blockTable = transaction.GetObject(database.BlockTableId, OpenMode.ForRead) as BlockTable;

                    //Open the block table record model space for write
                    BlockTableRecord blockTableRecord = (BlockTableRecord)transaction.GetObject(blockTable[BlockTableRecord.ModelSpace], OpenMode.ForWrite);

                    Line line = new Line(new Point3d(0, 0, 0), new Point3d(10, 10, 0));
                    blockTableRecord.AppendEntity(line);

                    transaction.AddNewlyCreatedDBObject(line, true);

                    transaction.Commit();
                }
            }
        }
    }

    private void AddCircleToDrawing()
    {
        using (DocumentLock lockedDocument = Application.DocumentManager.MdiActiveDocument.LockDocument())
        {
            using (Database database = Application.DocumentManager.MdiActiveDocument.Database)
            {
                using (Transaction transaction = database.TransactionManager.StartTransaction())//Start the transaction
                {
                    //Open the block table for read
                    BlockTable blockTable = transaction.GetObject(database.BlockTableId, OpenMode.ForRead) as BlockTable;

                    //Open the block table record model space for write
                    BlockTableRecord blockTableRecord = (BlockTableRecord)transaction.GetObject(blockTable[BlockTableRecord.ModelSpace], OpenMode.ForWrite);

                    Circle circle = new Circle(new Point3d(0, 0, 0), new Vector3d(0, 0, 0), 10);
                    blockTableRecord.AppendEntity(circle);

                    transaction.AddNewlyCreatedDBObject(circle, true);

                    transaction.Commit();
                }
            }
        }
    }

注入:这种方法消除了重复的代码,但是我认为可读性很差。

[CommandMethod("Test", CommandFlags.Session)]
    public void Test()
    {
        PerformActionOnBlockTable(new CircleDrawer());
        PerformActionOnBlockTable(new LineDrawer());
    }

    public interface IDraw
    {
        DBObject DrawObject(BlockTableRecord blockTableRecord);
    }

    public class CircleDrawer : IDraw
    {
        public DBObject DrawObject(BlockTableRecord blockTableRecord)
        {
            Circle circle = new Circle(new Point3d(0, 0, 0), new Vector3d(0, 0, 0), 10);
            blockTableRecord.AppendEntity(circle);

            return circle;
        }
    }

    public class LineDrawer : IDraw
    {
        public DBObject DrawObject(BlockTableRecord blockTableRecord)
        {
            Line line = new Line(new Point3d(0, 0, 0), new Point3d(10, 10, 0));
            blockTableRecord.AppendEntity(line);

            return line;
        }
    }

    private void PerformActionOnBlockTable(IDraw drawer)
    {
        using (DocumentLock lockedDocument = Application.DocumentManager.MdiActiveDocument.LockDocument())
        {
            using (Database database = Application.DocumentManager.MdiActiveDocument.Database)
            {
                using (Transaction transaction = database.TransactionManager.StartTransaction())//Start the transaction
                {
                    //Open the block table for read
                    BlockTable blockTable = transaction.GetObject(database.BlockTableId, OpenMode.ForRead) as BlockTable;

                    //Open the block table record model space for write
                    BlockTableRecord blockTableRecord = (BlockTableRecord)transaction.GetObject(blockTable[BlockTableRecord.ModelSpace], OpenMode.ForWrite);

                    DBObject newObject = drawer.DrawObject(blockTableRecord);

                    transaction.AddNewlyCreatedDBObject(newObject, true);

                    transaction.Commit();
                }
            }
        }
    }

注入Func :这似乎给了我类似的结果,具有更好的可读性。

[CommandMethod("Test", CommandFlags.Session)]
    public void Test()
    {
        PerformActionOnBlockTable(AddLineToDrawing);
        PerformActionOnBlockTable(AddCircleToDrawing);
    }

    private void PerformActionOnBlockTable(Func<BlockTableRecord, DBObject> action)
    {
        using (DocumentLock lockedDocument = Application.DocumentManager.MdiActiveDocument.LockDocument())
        {
            using (Database database = Application.DocumentManager.MdiActiveDocument.Database)
            {
                using (Transaction transaction = database.TransactionManager.StartTransaction())//Start the transaction
                {
                    //Open the block table for read
                    BlockTable blockTable = transaction.GetObject(database.BlockTableId, OpenMode.ForRead) as BlockTable;

                    //Open the block table record model space for write
                    BlockTableRecord blockTableRecord = (BlockTableRecord)transaction.GetObject(blockTable[BlockTableRecord.ModelSpace], OpenMode.ForWrite);

                    DBObject newObject = action(blockTableRecord);

                    transaction.AddNewlyCreatedDBObject(newObject, true);

                    transaction.Commit();
                }
            }
        }
    }

    private DBObject AddLineToDrawing(BlockTableRecord blockTableRecord)
    {
        Line line = new Line(new Point3d(0, 0, 0), new Point3d(10, 10, 0));
        blockTableRecord.AppendEntity(line);

        return line;
    }

    private DBObject AddCircleToDrawing(BlockTableRecord blockTableRecord)
    {
        Circle circle = new Circle(new Point3d(0, 0, 0), new Vector3d(0, 0, 0), 10);
        blockTableRecord.AppendEntity(circle);

        return circle;
    }

老实说,我对DI并没有做太多事情,所以我对此很陌生。你们中任何更有经验的开发人员可以给我两种不同方法的专业意见吗?最后一种方法中是否有任何危险的信号?它似乎比第二种方法更具可读性。也许我什至不完全了解注射剂...预先感谢您的输入!

参考方案

您可以进行简单的重构,而不是提供的选项:

[CommandMethod("Test", CommandFlags.Session)]   
public void Test() {   
  AddLineToDrawing();   
  AddCircleToDrawing();   
}  

private void AddLineToDrawing() {   
  CreateObjectOnBlockTable(
    new Line(new Point3d(0, 0, 0), new Point3d(10, 10, 0)));   
}   

private void AddCircleToDrawing() {   
  CreateObjectOnBlockTable(
    new Circle(new Point3d(0, 0, 0), new Vector3d(0, 0, 0), 10));   
}   

private void CreateObjectOnBlockTable(DBObject dbObject) { 
  using (var lockedDocument = Application.DocumentManager.MdiActiveDocument.LockDocument()) 
  using (var database = Application.DocumentManager.MdiActiveDocument.Database) 
  using (var transaction = database.TransactionManager.StartTransaction()) {
    // Open the block table for read 
    var blockTable = (BlockTable)transaction.GetObject(database.BlockTableId, OpenMode.ForRead); 

    // Open the block table record model space for write 
    var blockTableRecord = (BlockTableRecord)transaction.GetObject(blockTable[BlockTableRecord.ModelSpace], OpenMode.ForWrite); 

    blockTableRecord.AppendEntity(dbObject); 
    transaction.AddNewlyCreatedDBObject(dbObject, true); 
    transaction.Commit(); 
  } 
} 

我认为这更具可读性。

更新:为了运行特殊的逻辑,我喜欢使用委托的想法。我将这样重构代码:

private void CreateObjectOnBlockTable(DBObject dbObject) {
  PerformActionOnBlockTable((transaction, blockTableRecord) => {
    blockTableRecord.AppendEntity(dbObject);  
    transaction.AddNewlyCreatedDBObject(dbObject, true);    
  });
}

private void PerformActionOnBlockTable(Action<Transaction, BlockTableRecord> action) {  
  using (var lockedDocument = Application.DocumentManager.MdiActiveDocument.LockDocument())  
  using (var database = Application.DocumentManager.MdiActiveDocument.Database)  
  using (var transaction = database.TransactionManager.StartTransaction()) { 
    // Open the block table for read  
    var blockTable = (BlockTable)transaction.GetObject(database.BlockTableId, OpenMode.ForRead);  

    // Open the block table record model space for write  
    var blockTableRecord = (BlockTableRecord)transaction.GetObject(blockTable[BlockTableRecord.ModelSpace], OpenMode.ForWrite);  

    // Run specific logic
    action(transaction, blockTableRecord);

    transaction.Commit();  
  }  
}  

(其余代码将相同)

可以使用事务和块表记录重用PerformActionOnBlockTable来运行任意逻辑。

当s1 = new Student()和s2 = new Student()时,如何更改Student类,使s1 == s2返回true? - java

在我的一次采访中,一名面试官问我:给定一个Student类和两个对象s1和s2:s1 = new Student(); s2 = new Student(); s1 == s2如何返回true?我告诉他让Student类成为一个单例,但他说不,我们必须更改类级别,以便s1 == s2返回true。注意:我们需要更改Student类。请不要回复s1=s2。有什…

使用iText库根据给定的格式创建PDF - java

我正在用Java开发小型项目,我想从数据库中获取内容并将其写入PDF文件。我尝试使用Google搜索,并提出了iText Library。任何人都可以指导创建看起来像所附图像的PDFPS:我对JAVA还是很陌生,这是我的第一个Java项目。 参考方案 我已经完成了大多数用例的快速实现。这是代码:首先,我们定义一个小类,充当发票中的单个记录。static cl…

是否可以阻止用户下载SQLite文件? - php

我正在从here学习SQLite3;它确实很好并且可移植,但是如果有人以某种方式知道数据库文件名test.db然后直接下载它怎么办?它可能比SQL注入更为危险,因为攻击者可以轻松获取整个数据库的副本。 参考方案 您可以限制.db文件中的.htaccess文件以执行相同的操作,将这行代码添加到位于根目录中的.htaccess文件中<Files ~ �…

使用GridLayout对jpanels组件进行垂直对齐 - java

我正在使用Java swing库将KenKen作为我的学期项目。为了对齐,我使用了gridbag和gridlayout,但是现在我想向用户界面添加JPanel的另一个组件。这些屏幕截图将使问题更加清楚:现在,我在最左侧的面板中选择要向其添加候选对象的网格单元。它扰乱了网格和面板的相邻对齐。以下是具有各自布局的面板: JPanel buttonPanel = …

如何获取Firebase数据? - python

我是python和firebase的新手,并且试图扩展我的firebase数据库。我有这种格式的数据库每只猫都有成千上万的数据。我要获取的是猫的名字,并将它们放入数组中。例如,我希望输出为['cat1','cat2'....]我正在使用本教程http://ozgur.github.io/python-firebase/from firebase import…