[英]Intercept method calls in a generic class
我有這個代碼:
abstract class CommunicationChannel<Client> : IDisposable where Client : class, IDisposable {
protected Client client;
public void Open() {
try
{
client = CreateClient();
}
catch (Exception)
{
client.Dispose();
throw;
}
}
public virtual void Dispose() {
client.Dispose();
}
private Client CreateClient()
{
return Activator.CreateInstance<Client>();
}
}
class Communicator : CommunicationChannel<Client>
{
// here I have specific methods
void Method1(args) {
Open();
try {
client.Method1(args);
}
catch(Exception) {
// Cleanup
}
}
// this is getting too verbose already
void Method2(args) {
Open();
try {
client.Method2(args);
}
catch(Exception) {
// Cleanup
}
}
}
class Client: IDisposable {
public void Dispose()
{
}
}
我希望在基類CommunicationChannel中能夠以某種方式攔截與客戶端相關的所有調用,並在將它們傳播到派生類CommunicationChannel之前處理異常。 基類的泛型參數可以包含不同的方法(在我的示例中,我們只有方法1)
理想情況下,我想要一個解決方案,我不必調用CommunicationChannel.CallMethod(“Method1”,args)。
您可以使client
私有並強制子類在Func
或Action
訪問它。 然后你可以在邏輯之前/之后添加你:
abstract class CommunicationChannel<Client> : IDisposable where Client : class, IDisposable
{
private Client client;
protected TResult WithClient<TResult>(Func<Client, TResult> f)
{
this.Open();
try
{
return f(client);
}
catch (Exception)
{
//cleanup
}
return default(TResult);
}
protected void WithClient(Action<Client> act)
{
WithClient<object>(c => { act(c); return null; })
}
}
你的子類可以這樣做:
class Communicator : CommunicationChannel<Client>
{
bool Method1(args)
{
return WithClient<bool>(c => { return c.Method1(args); });
}
}
我認為使用AOP(面向方面編程)是一個很好的例子。
你可以做的是設置一個方面OnEntry,執行Open方法並使用OnException方法捕獲異常。
然后,您所要做的就是使用Attribute來裝飾要使用該方面的方法
我用PostSharp演示了我的意思:
public class CommunicationAspect : OnMethodBoundaryAspect
{
public override void OnEntry(MethodExecutionArgs args)
{
var communicationObject = args.Instance as CommunicationObject;
communicationObject.Open();
args.FlowBehavior = FlowBehavior.Continue;
}
public override void OnException(MethodExecutionArgs args)
{
_logger.log(string.Format("Exception {0} has occured on method {1}", args.Exception, args.Method.Name));
}
}
然后,使用以下屬性裝飾您的方法:
class Communicator : CommunicationChannel<Client>
{
[CommunicationAspect]
void Method1(args)
{
client.Method1(args);
}
[CommunicationAspect]
void Method2(args)
{
client.Method2(args);
}
}
PostSharp是一個很棒的框架,讓它很容易上手,我建議你研究一下。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.