是否有一种方法在c# /VB.NET假继承

本文关键字:VB NET 继承 方法 一种 是否 | 更新日期: 2023-09-27 18:17:57

假设我想继承System.Data.SqlClient.SqlTransaction,这是密封。假设我只想在SqlTransaction周围放一个包装,并且总是使用MyTransaction而不是SqlTransaction。是否有一种方法可以使用隐式/扩展操作符将MyTransaction转换为SqlTransaction ?

是否有一种方法在c# /VB.NET假继承

您可以创建一个具有内部事务变量的类,然后公开方法和属性。就像这样:

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实现的相同接口,则可以非常接近。