是否有一种方法在c# /VB.NET假继承
本文关键字:VB NET 继承 方法 一种 是否 | 更新日期: 2023-09-27 18:17:57
假设我想继承System.Data.SqlClient.SqlTransaction
,这是密封。假设我只想在SqlTransaction
周围放一个包装,并且总是使用MyTransaction
而不是SqlTransaction
。是否有一种方法可以使用隐式/扩展操作符将MyTransaction
转换为SqlTransaction
?
您可以创建一个具有内部事务变量的类,然后公开方法和属性。就像这样:
public class MyTransaction
{
System.Data.SqlTransaction myTx = someConnection.CreateTransaction();
public void CommitTransaction() : {
myTx.CommitTransaction()
}
}
您也可以使它继承自DbTransaction,然后重写抽象和虚拟过程以使用内部myTx变量,但它开始变得有点复杂,没有明显的真正原因…
如果你真的想要隐式转换(虽然我不建议这样做,因为这是一个可怕的想法和一个可怕的设计,在我看来),你可以这样做:
class MyTransaction
{
private readonly SqlTransaction _transaction;
public MyTransaction(SqlConnection conn)
{
_transaction = conn.BeginTransaction();
}
public SqlTransaction Transaction
{
get
{
return _transaction;
}
}
public static implicit operator SqlTransaction(MyTransaction t)
{
return t.Transaction;
}
}
如果您只是对在类中添加其他方法感兴趣,您可以使用扩展方法。这不会让您访问任何内部状态,也不会允许您重写行为,但它可以让您添加有限的功能。我不知道有什么方法可以从一个密封类继承。
您可以像其他人提到的那样创建一个真正的包装器对象,但是您将无法以多态方式使用它来代替原始对象。
好,那么排除继承并专注于您真正想要解决的任务(基于注释线程)。
在过去,我已经成功地通过一个helper库运行所有调用,并在那里实现逻辑。在过去,我用过SqlHelper,它是在Microsoft数据应用程序块中发布的。这是一个源代码模块,您可以根据自己的需要进行调整。您可以添加所需的任何日志记录或其他逻辑。
它还使代码非常可读。你可以这样做:
SqlHelper.ExecuteDataset()
用于查询返回的数据集,
SqlHelper.ExecuteScalar()
用于查询返回单个值,
SqlHelper.ExecuteNonQuery()
用于没有返回值的命令(如INSERT
)。
等。
不行,不能从SqlTransaction继承自定义类,也不能伪造自定义类。
然而,如果你正在做的事情的上下文允许你使用DbTransaction,你可以从DbTransaction继承你的自定义事务类,用你需要的任何其他功能包装一个SqlTransaction。
您确实有另一个选择,您可以使用Reflection.Emit()将您选择的接口添加到SqlTransaction,然后在新的MyTransaction类中使用相同的接口,然后您可以调用接口,而不是类。
请注意,这只会在您创建的库中起作用,或者专门使用反射修改加载的类型。
可以创建扩展方法
public static class SqlTransactionExtensions
{
public static void DoSomething(this SqlTransaction transaction, int myParameter)
{
// do something here
}
}
类必须是静态的。将神奇的单词this
放在第一个参数前面,该参数必须是您正在扩展的类的类型。您也可以扩展接口。如果你想使用这个扩展方法,那么你必须有一个using namspace
与这个扩展类的命名空间,如果它不是在你工作的同一个命名空间中定义的。
可以像调用SqlTransaction的常规方法一样调用扩展方法:
SqlTransaction t = new SqlTransaction();
t.DoSomething(5);
您可以定义自己的MyTransaction类作为SqlTransaction的包装器。在MyTransaction的私有字段中保留一个SqlTransaction实例。您的包装器将不会与SqlTransaction赋值兼容,但如果您实现SqlTransaction实现的相同接口,则可以非常接近。