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

时间:2011-12-14 19:39:33

标签: c# vb.net .net-2.0

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

8 个答案:

答案 0 :(得分:6)

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

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

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

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

答案 1 :(得分:3)

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

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

答案 2 :(得分:3)

如果真的想要隐式转换(虽然我不推荐它,因为它是一个可怕的想法和一个可怕的设计,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;
        }
    }

答案 3 :(得分:2)

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

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

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

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

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

SqlHelper.ExecuteNonQuery()表示没有返回的命令(如INSERT)。

答案 4 :(得分:1)

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

但是,如果你正在做的事情的上下文允许你使用DbTransaction,你可以从DbTransaction继承你的自定义事务类,用你需要的任何其他功能包装一个SqlTransaction。

答案 5 :(得分:1)

你还有另一种选择,你可以使用Reflection.Emit()将你选择的接口添加到SqlTransaction,然后在新的MyTransaction类中使用相同的接口,然后你可以调用接口该课程。

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

答案 6 :(得分:1)

您可以创建扩展方法。

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

答案 7 :(得分:0)

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