0

複数のオブジェクトを持つアプリケーションを準備しています。それぞれに整数の ID と文字列データがあります。同じIDを持つオブジェクトのデータを同じにしたい。このオブジェクトを SharedObject と呼びます (このオブジェクトは、一部のデータベース テーブルの ViewModel のように機能します)。

とても簡単だと言えるかもしれません。オブジェクトを 1 つ作成し、必要なときにいつでも参照できます。しかし、実際には、オブジェクトがいつどこで作成されるかを予測できないため、この方法はうまくいきません。

したがって、この問題を処理するために、SharedObject クラスに静的イベントを配置し、SharedObject データが変更されたときにそれを呼び出すことにしました (INotifyPropertyChanged の PropertyChanged イベントのように、私のものは静的です。これにより、SharedObject の各インスタンスに表示されます)。問題は、メモリリークだらけのプログラムになってしまうことです!!

昨夜、メモリ リークの問題を解決するには弱いイベント パターンを使用する必要があることを整理しました。

弱いイベント パターンの完全な実装を求めて昨夜ネットを検索しましたが、最終的には何も表示されなかったか、ページが削除されました。

最後に、弱いイベント パターンでそれを行う方法を見つけ、このアプローチをテストするテスト プロジェクトを作成しましたが、うまくいきませんでした。ReceiveWeakEvent イベントを呼び出すことができませんでした。

何か不足していますか?または、このパターンを実装する正しい方法は何ですか?

ちなみに、私はアプリケーションで Win XP をサポートする必要があるため .net 4 を使用しています (これは私の顧客が必要としているものです。それについて私に尋ねないでください)。そのため、一般的な WeakEventManager クラスを使用できません。

長い投稿で申し訳ありませんが、この問題は私が髪を引き裂くところだったので、事前に感謝します.

完全なアプリケーション コードは次のとおりです。

SharedObject クラス:

public class SharedObject :INotifyPropertyChanged,IWeakEventListener
{
    static WaekEvent sheardEvent = new WaekEvent();

    public event PropertyChangedEventHandler PropertyChanged;

    public int ID { get; private set; }

    public SharedObject(int id)
    {
        this.ID = id;
        SharedWeakEventManager.AddListener(sheardEvent, this);
    }

    string data;
    public string Data
    {
        get
        {
            return data;
        }
        set
        {
            if(value != data)
            {
                data = value;
                OnPropertyChanged("Data");
                sheardEvent.RiseSharedEvent(this, new PropertyChangedEventArgs("Data"));
            }
        }
    }

    protected virtual void OnPropertyChanged(string propName)
    {
        PropertyChangedEventHandler handler;
        lock (this)
        {
            handler = PropertyChanged;
        }
        if (handler != null)
            handler.Invoke(this, new PropertyChangedEventArgs(propName));
    }

    void OnSharedPropertyChaingo(object sender,PropertyChangedEventArgs e)
    {
        SharedObject s = sender as SharedObject;
        if (s == null || s.ID != ID)
            return;
        data = s.Data;
        OnPropertyChanged("Data");
    }


    public bool ReceiveWeakEvent(Type managerType, object sender, EventArgs e)
    {
        if(managerType == typeof(SharedWeakEventManager) && sender is SharedObject)
        {
            OnSharedPropertyChaingo(sender, e as PropertyChangedEventArgs);
        }
        return false;
    }
}

WaekEvent および SharedWeakEventManager クラス:

public class SharedObject 
{
    public event EventHandler SharedEvent;

    public void RiseSharedEvent(object sender, EventArgs args)
    {
        if (SharedEvent != null)
            SharedEvent.Invoke(sender, args);
    }
}
public class SharedWeakEventManager : WeakEventManager
{
    public static SharedWeakEventManager CurrentManager
    {
        get
        {
            var manager_type = typeof(SharedWeakEventManager);
            var manager = WeakEventManager.GetCurrentManager(manager_type) as SharedWeakEventManager;

            if (manager == null)
            {
                manager = new SharedWeakEventManager();
                WeakEventManager.SetCurrentManager(manager_type, manager);
            }

            return manager;
        }
    }

    public static void AddListener(WaekEvent source, IWeakEventListener listener)
    {
        CurrentManager.ProtectedAddListener(source, listener);
    }

    public static void RemoveListener(WaekEvent source, IWeakEventListener listener)
    {
        CurrentManager.ProtectedRemoveListener(source, listener);
    }

    protected override void StartListening(object source)
    {
        ((WaekEvent)source).SharedEvent += this.DeliverEvent;
    }

    protected override void StopListening(object source)
    {
        ((WaekEvent)source).SharedEvent -= this.DeliverEvent;
    }
}   

MainWindow の XAML 部分:

<Window x:Class="WpfApplication1.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="MainWindow" Height="350" Width="525">
<Grid>
    <ListView x:Name="View" Margin="10,49,10,10" SelectionChanged="ListView_SelectionChanged">
        <ListView.View>
            <GridView>
                <GridViewColumn Header="ID" Width="100" DisplayMemberBinding="{Binding ID}"/>
                <GridViewColumn Header="Data" Width="100" DisplayMemberBinding="{Binding Data}"/>
            </GridView>
        </ListView.View>
    </ListView>
    <Button Content="New" HorizontalAlignment="Left" VerticalAlignment="Top" Width="75" Margin="10,13.01,0,0" Click="Button_Click"/>
    <TextBox x:Name="IDText" HorizontalAlignment="Left" Height="23" TextWrapping="Wrap" Text="TextBox" VerticalAlignment="Top" Width="92" Margin="136.2,11,0,0"/>
    <TextBox x:Name="DataText" HorizontalAlignment="Left" Height="23" TextWrapping="Wrap" Text="TextBox" VerticalAlignment="Top" Width="92" Margin="280.799,11,0,0" TextChanged="DataText_TextChanged"/>
    <TextBlock HorizontalAlignment="Left" TextWrapping="Wrap" Text="ID" VerticalAlignment="Top" Margin="119.593,14,0,0"/>
    <TextBlock HorizontalAlignment="Left" TextWrapping="Wrap" Text="Data" VerticalAlignment="Top" Margin="251.106,15.01,0,0"/>
    <Button Content="Remove" HorizontalAlignment="Left" VerticalAlignment="Top" Width="75" Margin="377.799,12,0,0" Click="Button_Click_1"/>

</Grid>

MainWindow クラス:

public partial class MainWindow : Window
{
    private ObservableCollection<SharedObject> sharedObjects;
    public ObservableCollection<SharedObject> SharedObjects
    {
        get
        {
            if (sharedObjects == null)
                sharedObjects = new ObservableCollection<SharedObject>();
            return sharedObjects;
        }
    }

    public SharedObject SelelectedObject { get; set; }
    public MainWindow()
    {
        InitializeComponent();
        View.ItemsSource = SharedObjects;
    }

    private void Button_Click(object sender, RoutedEventArgs e)
    {
        int id;
        if (!int.TryParse(IDText.Text, out id))
            return;

        SharedObject x = new SharedObject(id);
        x.Data = DataText.Text;
        SharedObjects.Add(x);
    }

    private void Button_Click_1(object sender, RoutedEventArgs e)
    {
        if (SelelectedObject == null)
            return;
        SharedObjects.Remove(SelelectedObject);
        SelelectedObject = null;
    }

    private void DataText_TextChanged(object sender, TextChangedEventArgs e)
    {
        if (SelelectedObject != null)
            SelelectedObject.Data = DataText.Text;
    }

    private void ListView_SelectionChanged(object sender, SelectionChangedEventArgs e)
    {
        SelelectedObject = View.SelectedItem as SharedObject;
        if (SelelectedObject == null)
            return;
        IDText.Text = SelelectedObject.ID.ToString();
        DataText.Text = SelelectedObject.Data;
    }
}
4

0 に答える 0