繁体   English   中英

有没有办法在C#/ VB.NET中进行FAKE继承?

[英]Is there a way to FAKE inheritance in C#/VB.NET?

假设我想继承密封的 System.Data.SqlClient.SqlTransaction 我希望只是在SqlTransaction周围放置一个包装器,并始终使用MyTransaction而不是SqlTransaction 有没有办法可以使用Implicit / MyTransaction运算符将MyTransactionSqlTransaction

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

public class MyTransaction
{
    System.Data.SqlTransaction myTx = someConnection.CreateTransaction();

    public void CommitTransaction() :  {
        myTx.CommitTransaction()
    }
}

你也可以让它继承自DbTransaction,然后重写抽象和虚拟程序以使用内部myTx变量,但它开始变得有点复杂,没有明显的真正原因......

如果您只是想为类添加其他方法,可以使用扩展方法。 这不会让您访问任何内部状态,或允许您覆盖行为,但它会让您添加有限的功能。 我不知道有什么方法可以继承密封课程。

您可以像其他人提到的那样创建一个真正的包装器对象,但是您将无法以多态方式使用它来代替原始对象。

如果你真的想要隐式转换(虽然我不推荐它,因为它是一个可怕的想法和一个可怕的设计,IMO),你可以做这样的事情:

    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;
        }
    }

好的,所以排除了继承并专注于你真正想要解决的任务(基于评论线程)。

我过去成功通过帮助程序库运行所有调用并在那里实现逻辑。 过去,我使用过SqlHelper,它发布在Microsoft Data Application Block中 这是一个源模块,您可以根据自己的需要进行调整。 您可以添加所需的任何日志记录或其他逻辑。

它还使代码非常易读。 你可以这样做:

SqlHelper.ExecuteDataset()用于返回数据集的查询,

SqlHelper.ExecuteScalar()用于返回单个值的查询,

SqlHelper.ExecuteNonQuery()用于没有返回的命令(如INSERT的)。

等等

不,你不能让你的自定义类继承自SqlTransaction或伪造它。

但是,如果您正在执行的操作的上下文允许您使用DbTransaction,则可以从DbTransaction继承自定义事务类,使用您需要的任何其他功能将SqlTransaction包装在内部。

你有另一个选择,你可以使用Reflection.Emit()将你选择的接口添加到SqlTransaction,然后在你的新MyTransaction类中使用相同的接口然后你可以调用接口,而不是类。

请注意,这只能在您创建的库中使用,或者使用Reflection专门修改加载的类型。

您可以创建扩展方法。

public static class SqlTransactionExtensions
{
    public static void DoSomething(this SqlTransaction transaction, int myParameter)
    {
        // do something here
    }
}

该类必须是静态的。 将魔语this其中一定是要扩展的类的类型的拳头参数的前面。 您也可以扩展接口。 如果要使用此扩展方法,则必须using namspace具有此扩展类的命名空间的using namspace ,如果它未在您正在使用的同一命名空间中定义。

然后,您可以调用扩展方法,就像它是SqlTransaction的常规方法一样:

SqlTransaction t = new SqlTransaction();
t.DoSomething(5);

您可以将自己的MyTransaction类定义为SqlTransaction的包装器。 在MyTransaction中的私有字段中保留SqlTransaction的实例。 你的包装器不会与SqlTransaction兼容,但是如果实现SqlTransaction实现的相同接口,你可以非常接近。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM