ObservableObject

ObservableObject, INotifyPropertyChanged ve INotifyPropertyChanging arabirimlerini uygulayarak gözlemlenebilir olan nesneler için temel bir sınıftır. Özellik değişikliği bildirimlerini desteklemesi gereken her tür nesne için başlangıç noktası olarak kullanılabilir.

Platform API'leri:ObservableObject, TaskNotifier, TaskNotifier<T>

Nasıl çalışır?

ObservableObject aşağıdaki ana özelliklere sahiptir:

  • PropertyChanged ve PropertyChanging olaylarını kullanıma sunarak, INotifyPropertyChanged ve INotifyPropertyChanging için temel bir uygulama sağlar.
  • ObservableObject öğesinden türeyen türlerde özellik değerlerini kolayca ayarlamak ve uygun olayları otomatik olarak tetiklemek için kullanılabilen bir dizi SetProperty yöntemi sağlar.
  • SetPropertyAndNotifyOnCompletion yöntemini sağlar; bu yöntem, SetProperty ile benzerdir, ancak Task özelliklerini ayarlayabilme ve atanan görevler tamamlandığında bildirim olaylarını otomatik olarak tetikleyebilme özelliğine sahiptir.
  • OnPropertyChanged ve OnPropertyChanging yöntemlerini kullanıma sunar; bu yöntemler, bildirim olaylarının nasıl tetikleneceğini özelleştirmek için türetilmiş türlerde geçersiz kılınabilir.

Basit özellik

Özel bir özelliğe bildirim desteği uygulama örneği aşağıda verilmiştir:

public class User : ObservableObject
{
    private string name;

    public string Name
    {
        get => name;
        set => SetProperty(ref name, value);
    }
}

Sağlanan SetProperty<T>(ref T, T, string) yöntem özelliğin geçerli değerini denetler ve farklıysa güncelleştirir ve ardından ilgili olayları otomatik olarak yükseltir. Özellik adı özniteliğinin kullanımıyla otomatik olarak yakalanır, bu nedenle hangi özelliğin [CallerMemberName] güncelleştirileceğini el ile belirtmenize gerek yoktur.

Gözlemlenebilir olmayan bir modeli sarmalama

Örneğin veritabanı öğeleriyle çalışırken yaygın bir senaryo, veritabanı modelinin özelliklerini aktaran ve gerektiğinde özellik değişikliği bildirimlerini yükselten bir sarmalama "bağlanabilir" modeli oluşturmaktır. Bu, arabirimi uygulamayan INotifyPropertyChanged modellere bildirim desteği eklemek istediğinizde de gereklidir. ObservableObject bu işlemi daha basit hale getirmek için ayrılmış bir yöntem sağlar. Aşağıdaki örnekte, User, ObservableObject öğesinden kalıtım almadan bir veritabanı tablosunu doğrudan eşleyen bir modeldir:

public class ObservableUser : ObservableObject
{
    private readonly User user;

    public ObservableUser(User user) => this.user = user;

    public string Name
    {
        get => user.Name;
        set => SetProperty(user.Name, value, user, (u, n) => u.Name = n);
    }
}

Bu durumda aşırı yüklemeyi kullanıyoruz SetProperty<TModel, T>(T, T, TModel, Action<TModel, T>, string) . İmza öncekinden biraz daha karmaşıktır. Bu, önceki senaryoda olduğu gibi bir yedekleme alanına erişimimiz olmasa bile kodun son derece verimli olmasına izin vermek için gereklidir. Farklı bileşenlerin rolünü anlamak için bu yöntem imzasının her bir bölümünü ayrıntılı olarak inceleyebiliriz:

  • TModel, sardığımız modelin türünü belirten bir tür argümanıdır. Bu durumda, bizim sınıfımız User olacak. Bunun açıkça belirtilmesine gerek olmadığını unutmayın; C# derleyicisi, SetProperty yöntemini nasıl çağırdığımıza bakarak bunu otomatik olarak çıkaracaktır.
  • T , ayarlamak istediğimiz özelliğin türüdür. TModel'ya benzer şekilde, bunun çıkarımı otomatik olarak yapılır.
  • T oldValue ilk parametredir ve bu durumda sarmaladığımız özelliğin geçerli değerini geçirmek için kullanıyoruz user.Name .
  • T newValue, özelliğe atanacak yeni değerdir ve burada özellik ayarlayıcısındaki giriş değeri olan value değerini geçiriyoruz.
  • TModel model sarmaladığımız hedef modeldir, bu örnekte alanda user depolanan örneği geçiriyoruz.
  • Action<TModel, T> callback özelliğin yeni değeri geçerli değerden farklıysa ve özelliğin ayarlanması gerekiyorsa çağrılacak bir işlevdir. Bu, hedef modeli ve ayarlanacak yeni özellik değerini girdi olarak alan bu geri çağırma işlevi tarafından yapılır. Bu durumda yalnızca input değerini (n adını verdiğimiz değeri), u.Name = n yaparak Name özelliğine atıyoruz. C# derleyicisinin geri çağırma işlevini önbelleğe alıp bir dizi performans iyileştirmesi gerçekleştirmesine olanak tanıdığından, geçerli kapsamdaki değerleri yakalamaktan kaçınmak ve yalnızca geri çağırmaya giriş olarak verilenlerle etkileşimde bulunabilmek burada önemlidir. İşte bu yüzden burada doğrudan user alanına ya da setter içindeki value parametresine erişmiyoruz; bunun yerine yalnızca lambda ifadesinin giriş parametrelerini kullanıyoruz.

SetProperty<TModel, T>(T, T, TModel, Action<TModel, T>, string) yöntemi, son derece kompakt bir API sağlarken hem alma hem de hedef özellikleri ayarlamayı üstlenirken bu sarmalama özelliklerinin oluşturulmasını son derece basit hale getirir.

Not

LinQ ifadeleri kullanılarak, özellikle durum ve geri çağırma parametreleri yerine tür Expression<Func<T>> parametresi aracılığıyla bu yöntemin uygulanmasıyla karşılaştırıldığında, bu şekilde elde edilebilecek performans geliştirmeleri gerçekten önemlidir. Özellikle, bu sürüm LINQ ifadelerini kullanandan yaklaşık 200 kat daha hızlıdır ve hiç bellek ayırması yapmaz.

Task<T> özelliklerini işleme

Özellik bir Task özellikse, bağlamaların doğru zamanda güncelleştirilmesi için görev tamamlandıktan sonra bildirim olayının da tetiklenmesi gerekir. Örneğin, görev tarafından temsil edilen işlemle ilgili bir yükleme göstergesi veya diğer durum bilgilerini görüntülemek için. ObservableObject bu senaryo için bir API'ye sahiptir:

public class MyModel : ObservableObject
{
    private TaskNotifier<int>? requestTask;

    public Task<int>? RequestTask
    {
        get => requestTask;
        set => SetPropertyAndNotifyOnCompletion(ref requestTask, value);
    }

    public void RequestValue()
    {
        RequestTask = WebService.LoadMyValueAsync();
    }
}

SetPropertyAndNotifyOnCompletion<T>(ref TaskNotifier<T>, Task<T>, string) Burada yöntem hedef alanı güncelleştirme, varsa yeni görevi izleme ve görev tamamlandığında bildirim olayını başlatma ile ilgilenir. Bu şekilde, bir görev özelliğine bağlanmak ve durumu değiştiğinde bildirim almak mümkündür. TaskNotifier<T>, ObservableObject tarafından sağlanan, hedef bir Task<T> örneğini saran ve bu yöntem için gerekli bildirim mantığını sağlayan özel bir türdür. Yalnızca genel bir Task öğeniz varsa, TaskNotifier türünü doğrudan da kullanabilirsiniz.

Not

SetPropertyAndNotifyOnCompletion yöntemi, Microsoft.Toolkit paketindeki NotifyTaskCompletion<T> türünün kullanımının yerini almak üzere tasarlanmıştır. Bu tür kullanılıyorsa, yalnızca içteki Task (veya Task<TResult>) özelliğiyle değiştirilebilir ve ardından bu değeri ayarlamak ve değişiklik bildirimlerini tetiklemek için SetPropertyAndNotifyOnCompletion yöntemi kullanılabilir. NotifyTaskCompletion<T> türünün sunduğu tüm özellikler, Task örnekleri üzerinde doğrudan kullanılabilir.

Örnekler