我有一个向 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();
}
}
}
}
注入(inject):这种方法消除了重复的代码,但我认为可读性很差。
[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();
}
}
}
}
注入(inject) 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 没有做过太多的事情,所以我对此还很陌生。你们中有哪位更有经验的开发人员能给我这两种不同方法的优点/缺点吗?最后一种方法中有什么是危险信号吗?它似乎比第二种方法更具可读性。也许我什至没有完全理解注入(inject)...提前感谢您的输入!
最佳答案
您可以进行简单的重构而不是您提供的选项:
[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();
}
}
我认为这更具可读性。
更新:为了运行特殊逻辑,我喜欢使用委托(delegate)的想法。我会像这样重构代码:
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
可以重复使用以使用事务和 block 表记录运行任意逻辑。
关于c# - 干净的代码 : Readable Dependency Injection suggestions?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3824749/