2011-09-24 78 views
6

這兩個類都包含引發事件的另一個私有類。然後這兩個班級將這些事件重新提交給客戶。你如何用相同的重複事件重構兩個類?

不幸的是,兩個類都有此完全相同的代碼:

public class FirstClass 
{ 
    public delegate void FooEventHandler(string foo); 
    public delegate void BarEventHandler(string bar); 
    public delegate void BazEventHandler(string baz); 

    public event FooEventHandler Foo; 
    public event BarEventHandler Bar; 
    public event BazEventHandler Baz; 

    private PrivateObject privateObject; 

    public FirstClass() 
    { 
     privateObject.Foo += FirstClass_Foo; 
     privateObject.Bar += FirstClass_Bar; 
     privateObject.Baz += FirstClass_Baz; 
    } 

    private void FirstClass_Foo(string foo) 
    { 
     if (Foo != null) 
     { 
      Foo(foo); 
     } 
    } 

    private void FirstClass_Bar(string bar) 
    { 
     if (Bar != null) 
     { 
      Bar(bar); 
     } 
    } 

    private void FirstClass_Baz(string baz) 
    { 
     if (Baz != null) 
     { 
      Baz(baz); 
     } 
    } 
} 

正如你所看到的,我不得不從私人對象重新引發事件。這是多餘的。我嘗試使用繼承,並將此重複的代碼放在基類中,但我不斷收到類似的錯誤:

事件'BaseClass.Foo'只能出現在+ =或 - =的左側從內部使用)

有誰知道如何擺脫這個重複的代碼?

回答

5

如何將私有對象的事件公開爲包裝的屬性?如,

public class ExternalClass 
{ 
    private InternalClass _internalObject = new InternalClass(); 

    public event InternalClass.someDelegate SomeEvent 
    { 
     add 
     { 
      _internalObject.SomeEvent += value; 
     } 
     remove 
     { 
      _internalObject.SomeEvent -= value; 
     } 
    } 
} 

public class InternalClass 
{ 
    public delegate void someDelegate(string input); 
    public event someDelegate SomeEvent; 
} 

如果你熟悉C#屬性你可能已經知道了getset關鍵字。關鍵字add/remove基本上是相同的東西,只有當您嘗試向屬性中添加或刪除值時纔會觸發它們。

因此,當您命令(聯合國)將您的代表註冊到ExternalClass.SomeEvent時,您實際上(不)註冊到InternalClass.SomeEvent事件。

如果你不熟悉c#屬性,http://msdn.microsoft.com/en-us/library/x9fsa0sw(v=vs.80).aspx會幫助你。

+2

你最好不要使用的OnEvent爲您的活動的名稱。 OnEvent是提升/解散事件方法的標準名稱。否則,我同意你的迴應。 –

+0

非常感謝您的更正:) – Andrea

+0

Andrea:感謝您的回覆!不幸的是,我正在按照這個代碼所做的事情來處理一些問題。我從來沒有聽說過'add'和'remove'關鍵字o_O你能解釋一下這個代碼嗎? –

0

我認爲這會對你有用。公共接口允許PrivateObject保持內部。唯一的另一個技巧是必須在構造函數中調用RegisterIFooEvents。在控制檯應用程序

public interface IFooEvents 
{ 
    event BaseClass.FooEventHandler Foo; 
    event BaseClass.BarEventHandler Bar; 
    event BaseClass.BazEventHandler Baz; 
} 

internal class PrivateObject : IFooEvents 
{ 
    public event BaseClass.FooEventHandler Foo; 
    public event BaseClass.BarEventHandler Bar; 
    public event BaseClass.BazEventHandler Baz; 

    public void ChangeFoo(string foo) 
    { 
     if (Foo != null) 
     { 
      Foo(foo); 
     } 
    } 
} 

public abstract class BaseClass : IFooEvents 
{ 
    public delegate void BarEventHandler(string bar); 
    public delegate void BazEventHandler(string baz); 
    public delegate void FooEventHandler(string foo); 

    private IFooEvents _fooEvents; 

    public event FooEventHandler Foo 
    { 
     add { _fooEvents.Foo += value; } 
     remove { _fooEvents.Foo -= value; } 
    } 

    public event BarEventHandler Bar 
    { 
     add { _fooEvents.Bar += value; } 
     remove { _fooEvents.Bar -= value; } 
    } 

    public event BazEventHandler Baz 
    { 
     add { _fooEvents.Baz += value; } 
     remove { _fooEvents.Baz -= value; } 
    } 

    protected void RegisterIFooEvents(IFooEvents fooEvents) 
    { 
     _fooEvents = fooEvents; 
    } 
} 

public class FirstClass : BaseClass 
{ 
    private readonly PrivateObject _privateObject; 

    public FirstClass() 
    { 
     _privateObject = new PrivateObject(); 
     RegisterIFooEvents(_privateObject); 
    } 

    public void ChangeFoo(string foo) 
    { 
     _privateObject.ChangeFoo(foo); 
    } 
} 

試運行:

class Program 
{ 
    static void Main(string[] args) 
    { 
     var class1 = new FirstClass(); 
     class1.Foo += EventRaised; 
     class1.ChangeFoo("TEST"); 

    } 

    static void EventRaised(string arg) 
    { 
     Console.WriteLine(arg); 
    } 
}