Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/322.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 从基类C获取隐藏成员#_C#_Spotfire - Fatal编程技术网

C# 从基类C获取隐藏成员#

C# 从基类C获取隐藏成员#,c#,spotfire,C#,Spotfire,在TIBCO Spotfire中(我无法控制它们的代码),有一个抽象类-DocumentNode,它的属性事务实现如下(根据反汇编): 那么DocumentNode实现了什么呢 public interface ITransactions { AggregatedTransactionHandle BeginAggregatedTransaction(); void ExecuteInvisibleTransaction(Executor executor); voi

在TIBCO Spotfire中(我无法控制它们的代码),有一个抽象类-DocumentNode,它的属性事务实现如下(根据反汇编):

那么DocumentNode实现了什么呢

public interface ITransactions
{
    AggregatedTransactionHandle BeginAggregatedTransaction();

    void ExecuteInvisibleTransaction(Executor executor);

    void ExecuteStickyTransaction(Guid guid, Executor executor);

    void ExecuteTransaction( Executor executor);
}
遗嘱执行人在哪里

delegate void Executor()
DocumentNode(同样根据反汇编)实现如下接口:

[ApiVersion("2.0")]
void ITransactions.ExecuteTransaction(Executor executor) => this.Transaction("Anonymous transaction", executor);

[ApiVersion("2.0")]
void ITransactions.ExecuteInvisibleTransaction(Executor executor) => this.InvisibleTransaction(executor);

[ApiVersion("2.0")]
void ITransactions.ExecuteStickyTransaction(Guid guid, Executor executor) => this.StickyTransaction(guid, executor);

[ApiVersion("2.0")]
public INodeContext Context
{
  [ApiVersion("2.0")] get => (INodeContext) this;
}

[ApiVersion("2.0")]
public ITransactions Transactions
{
  [ApiVersion("2.0")] get => (ITransactions) this;
}
但仅通过事务属性公开,而不是直接通过DocumentNode公开。 我可以控制的代码有许多类继承自DocumentNode,并过度使用ExecuteTransaction,从而导致嵌套事务。 典型用途:

this.Transactions.ExecuteTransaction(...
内部Spotfire有一些关于内部事务启动时外部事务可能处于何种状态的规则,并且在状态不匹配时抛出异常。我无法访问该内部状态,但如果捕获到此类异常,我们可以在不启动事务的情况下运行executor,我会对解决方案感到满意。 我还需要将代码更改保持在最低限度(我就是这么做的)

因此,我计划将一些从DocumentNode继承的类改为从DocumentNodeExt继承

public class DocumentNodeExt : DocumentNode
{
    public DocumentNodeExt() : base()
    { }

    public DocumentNodeExt(SerializationInfo info, StreamingContext context)
        : base(info, context)
    { }

    public new ITransactions Transactions
    {
        get { return this; }
    }


    public AggregatedTransactionHandle BeginAggregatedTransaction()
    {
        return base.Transactions.BeginAggregatedTransaction(); // stack overflow
        // return ((DocumentNode)this).Transactions.BeginAggregatedTransaction(); // stack overflow
    }

    public void ExecuteInvisibleTransaction(Executor executor)
    {
        try
        {
            base.Transactions.ExecuteInvisibleTransaction(executor);
        }
        catch (InvalidOperationException)
        {
            executor();
        }
    }

    public void ExecuteStickyTransaction(Guid guid, Executor executor)
    {
        base.Transactions.ExecuteStickyTransaction( guid,  executor);
    }

    void ExecuteTransaction(Executor executor)
    {
        try
        {
            base.Transactions.ExecuteTransaction(executor);
        }
        catch (InvalidOperationException)
        {
            executor();
        }
    }
}
问题是:因为DocumentNode.Transactions不是虚拟的,所以我不能在派生类中重写它。我只能通过“新建”来隐藏它, 但是,我如何调用DocumentNode的ExecuteTransaction实现呢? base没有方法ExecuteTransaction和base。事务与此相同。事务

我可以忘记隐藏事务并简单地实现ITransactions,但是接下来我还需要将典型调用从

this.Transactions.ExecuteTransaction(... 
this.Transactions.ExecuteTransaction(... 


这比我的“配额”允许的代码更改要多。

您只能包装
ITransactions
成员

public class DocumentNode : ITransactions
{
    void ITransactions.ExecuteInvisibleTransaction() => Console.WriteLine("ExecuteInvisibleTransaction in DocumentNode");
    public ITransactions Transactions => this;
}

public class DocumentNodeExt : DocumentNode
{
    public new ITransactions Transactions { get; }
    
    public DocumentNodeExt()
    {
        Transactions = new TransactionsWrapper(this);
    }
}

public class TransactionsWrapper : ITransactions
{
    private readonly ITransactions _transactions;
    public TransactionsWrapper(ITransactions transactions)
    {
        _transactions = transactions;
    }
    
    public void ExecuteInvisibleTransaction()
    {
        Console.WriteLine("ExecuteInvisibleTransaction in TransactionsWrapper");
        _transactions.ExecuteInvisibleTransaction();
    }
}

public interface ITransactions
{
    void ExecuteInvisibleTransaction();
}

请注意,
DocumentNodeExt
不继承接口,只有
ITransaction
成员的包装器继承接口

继承与基类相同的接口并调用基类成员是导致堆栈溢出的原因

由于我无法理解为什么会发生堆栈溢出,因此我为此提出了一个单独的问题

我可以忘记隐藏事务并简单地实现ITransactions,但是接下来我还需要将典型调用从

this.Transactions.ExecuteTransaction(... 
this.Transactions.ExecuteTransaction(... 

我不明白为什么。让我们确定以下几点:

  • 属于从
    DocumentNode
    继承的某种类型
  • DocumentNode
    实现
    ITransaction
  • 事务
    是非虚拟的
  • 事务
    在基本
    文档节点
    中定义为
    (ITransaction)此
  • 从1,2。四,。因此,对于
    DocumentNode
    事务的实现
    ,以下情况始终正确:

    this.ReferenceEquals(this.Transactions)
    
    因为4。它在所有不隐藏
    事务的子类中都必须为真,因为它们不能覆盖它。因此对
    this.ExecuteTransaction
    this.Transactions.ExecuteTransaction
    的调用必须相同,只要您没有在子类中进行任何奇怪的隐藏

    将其放入代码中,考虑代码的精简版本:

    public interface ITransactions
    {
        void ExecuteTransaction();
    }
    
    public class DocumentNode : ITransactions
    {
        void ITransactions.ExecuteTransaction() => Console.WriteLine("Base ExecuteTransaction");
        
        public ITransactions Transactions => (ITransactions) this;
    }
    
    public class ExtDocumentNode : DocumentNode, ITransactions
    {
        public void ExecuteTransaction() => Console.WriteLine("Overriden ExecuteTransaction");
    }
    
    public class Implementation : DocumentNode
    {
        public void Foo() => this.Transactions.ExecuteTransaction();
    }
    
    public class ExtImplementation : ExtDocumentNode
    {    
        public void Foo() => this.Transactions.ExecuteTransaction();
    }
    
    现在输入以下代码:

    var instance = new Implementation();
    var extInstance = new ExtImplementation();
    
    instance.Foo();
    extInstance.Foo();
    
    印刷品

    Base ExecuteTransaction
    Overriden ExecuteTransaction
    
    如预期(见附件)


    所以,如上所述,我要么完全没有抓住要点,要么你的问题不是问题。如果我错了,请纠正我。

    我修改了您的代码以显示OPs问题,至少我是这样理解的——通过将
    ExtImplementation
    强制转换为基类
    DocumentNode
    它调用的是基类方法,而不是标记为
    new
    的方法——如果该方法是虚拟的,并且可以被覆盖,那么问题就不存在了感谢您的努力。您遗漏的部分是ExecuteTransaction的ExtDocumentNode实现必须调用其中的DocumentNode实现,正如我上面的代码所示:base.Transactions.ExecuteTransaction(executor);这实际上不起作用,但告诉你我想叫基地一号。兰德·兰登,谢谢你的选角想法。在问这个问题之前,我确实试过了,但它对我不起作用。我怀疑是因为我必须在ExecuteTransaction的派生实现中调用ExecuteTransaction的“基本”实现,并且我必须通过事务属性调用它,因为ExecuteTransaction方法在我的代码中不是公共的。这就解释了为什么我没有隐藏方法,而是隐藏属性.Rand Random,我添加到你和V0ldek的代码中,以说明我在上面所说的@ILIABROUDNO-为了克服堆栈溢出,你需要像这样强制转换它
    ((DocumentNode)this.Transactions.).ExecuteTransaction()
    @ILIABROUDNO-您可以通过使用代理来克服这一问题,例如:谢谢您,Rand Random,我没有尝试过(我没有覆盖所有调用的代理),但我并不是真的很感兴趣——将每个调用都放在代理后面会产生相当严重的影响——在这浩瀚的代码海洋中有很多这样的调用,其中一些可能会使用其他技巧来实现自己的目标,而这些技巧与代理不兼容。另外,我怀疑它会在调试时让您的调用堆栈保持良好和有意义。啊哈!是的,最后一个似乎是解决办法。谢谢你。我把它标为答案。“你是想保持原样,还是想清理答案,这样无论是谁第一次进入,都只能看到最后一部分,我很乐意删除评论,这样一切都很好、整洁。”ILIABROUDNO我不打算清理,但这要到明天才会发生。需要睡眠。:)仅供参考,我很好奇为什么只有documentnodeext继承接口时才会发生stackoverflow,并在这里询问了这一点-
    Base ExecuteTransaction
    Overriden ExecuteTransaction