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