DependencyObjects için Güvenli Oluşturucu Desenleri

Genellikle, sınıf oluşturucuları sanal yöntemler veya temsilciler gibi geri çağırmaları çağırmamalıdır, çünkü oluşturucular türetilmiş bir sınıf için oluşturucuların temel başlatması olarak çağrılabilir. Sanalın girilmesi, belirli bir nesnenin tamamlanmamış başlatma durumunda yapılabilir. Ancak, özellik sisteminin kendisi, bağımlılık özellik sisteminin bir parçası olarak geri çağırmaları dahili olarak çağırır ve kullanıma sunar. Çağrısıyla SetValue bağımlılık özelliği değeri ayarlamak kadar basit bir işlem, belirlemenin herhangi bir yerinde bir geri çağırma içeriyor olabilir. Bu nedenle, bir oluşturucunun gövdesinde bağımlılık özelliği değerlerini ayarlarken dikkatli olmanız gerekir. Bu değer, türünüz temel sınıf olarak kullanıldığında sorunlu hale gelebilir. Bağımlılık özelliği durumları ve burada belgelenen doğal geri çağırmalarla ilgili belirli sorunları önleyen oluşturucuları uygulamak DependencyObject için belirli bir desen vardır.

Özellik Sistemi Sanal Yöntemleri

Aşağıdaki sanal yöntemler veya geri çağırmalar, bağımlılık özelliği değerini ayarlayan çağrının SetValue hesaplamaları sırasında çağrılabilir: ValidateValueCallback, PropertyChangedCallback, CoerceValueCallback, OnPropertyChanged. Bu sanal yöntemlerin veya geri çağırmaların her biri, Windows Presentation Foundation (WPF) özellik sisteminin ve bağımlılık özelliklerinin çok yönlülüğünü genişletmede belirli bir amaca hizmet eder. Özellik değeri belirlemeyi özelleştirmek için bu sanalları kullanma hakkında daha fazla bilgi için bkz . Bağımlılık Özelliği Geri Çağırmaları ve Doğrulama.

FXCop Kural Zorlama ve Özellik Sistemi Sanalları karşılaştırması

Derleme işleminizin bir parçası olarak Microsoft aracı FXCop kullanıyorsanız ve temel oluşturucuyu çağıran belirli WPF çerçeve sınıflarından türetilirseniz veya türetilmiş sınıflarda kendi bağımlılık özelliklerinizi uygularsanız, belirli bir FXCop kuralı ihlaliyle karşılaşabilirsiniz. Bu ihlalin ad dizesi:

DoNotCallOverridableMethodsInConstructors

Bu, FXCop için varsayılan genel kural kümesinin parçası olan bir kuraldır. Bu kuralın bildirebileceği, bağımlılık özellik sistemi üzerinden bir bağımlılık özellik sistemi sanal yöntemini çağıran bir izlemedir. Bu kural ihlali, bu konuda belgelenen önerilen oluşturucu desenlerini takip ettikten sonra bile görünmeye devam edebilir, bu nedenle FXCop kural kümesi yapılandırmanızda bu kuralı devre dışı bırakmanız veya gizlemeniz gerekebilir.

Sorunların çoğu mevcut sınıfları kullanmadan türetilen sınıflardan gelir

Bu kural tarafından bildirilen sorunlar, kendi yapı dizisinde sanal yöntemlerle uyguladığınız bir sınıf daha sonra türetildiğinde oluşur. Sınıfınızı mühürlerseniz veya sınıfınızın türetilmeyeceğini biliyor veya zorlarsanız, burada açıklanan noktalar ve FXCop kuralını motive eden sorunlar sizin için geçerli değildir. Ancak, temel sınıflar olarak kullanılması amaçlanacak şekilde sınıflar oluşturuyorsanız, örneğin şablon oluşturuyorsanız veya genişletilebilir bir denetim kitaplığı kümesi oluşturuyorsanız, oluşturucular için burada önerilen desenleri izlemeniz gerekir.

Varsayılan Oluşturucular Geri Çağırmalar Tarafından İstenen Tüm Değerleri Başlatmalıdır

Sınıfınız tarafından kullanılan tüm örnek üyeleri geçersiz kılmalar veya geri çağırmalar (Özellik Sistemi Sanalları bölümündeki listeden geri çağırmalar), bu değerlerden bazıları parametresiz oluşturucuların parametreleri aracılığıyla "gerçek" değerlerle doldurulmuş olsa bile sınıf parametresiz oluşturucunuzda başlatılmalıdır.

Aşağıdaki örnek kod (ve sonraki örnekler) bu kuralı ihlal eden ve sorunu açıklayan bir sözde C# örneğidir:

public class MyClass : DependencyObject  
{  
    public MyClass() {}  
    public MyClass(object toSetWobble)  
        : this()  
    {  
        Wobble = toSetWobble; //this is backed by a DependencyProperty  
        _myList = new ArrayList();    // this line should be in the default ctor  
    }  
    public static readonly DependencyProperty WobbleProperty =
        DependencyProperty.Register("Wobble", typeof(object), typeof(MyClass));  
    public object Wobble  
    {  
        get { return GetValue(WobbleProperty); }  
        set { SetValue(WobbleProperty, value); }  
    }  
    protected override void OnPropertyChanged(DependencyPropertyChangedEventArgs e)  
    {  
        int count = _myList.Count;    // null-reference exception  
    }  
    private ArrayList _myList;  
}  

Uygulama kodu çağırdığında new MyClass(objectvalue), parametresiz oluşturucuyu ve temel sınıf oluşturucularını çağırır. Ardından sanal yöntemini OnPropertyChanged sahip MyClassDependencyObjectolduğu üzerinde çağıran öğesini ayarlarProperty1 = object1. Geçersiz kılma, henüz başlatılmamış olan öğesine başvurur _myList.

Bu sorunlardan kaçınmanın bir yolu, geri çağırmaların yalnızca diğer bağımlılık özelliklerini kullandığından ve bu tür her bağımlılık özelliğinin kayıtlı meta verilerinin bir parçası olarak belirlenmiş bir varsayılan değere sahip olduğundan emin olmaktır.

Kasa Oluşturucu Desenleri

Sınıfınız temel sınıf olarak kullanılıyorsa tamamlanmamış başlatma risklerini önlemek için şu desenleri izleyin:

Temel başlatmayı çağıran parametresiz oluşturucular

Temel varsayılanı çağıran şu oluşturucuları uygulayın:

public MyClass : SomeBaseClass {  
    public MyClass() : base() {  
        // ALL class initialization, including initial defaults for
        // possible values that other ctors specify or that callbacks need.  
    }  
}  

Varsayılan olmayan (kolaylık) oluşturucular, temel imzalarla eşleşmiyor

Bu oluşturucular başlatmada bağımlılık özelliklerini ayarlamak için parametreleri kullanıyorsa, önce başlatma için kendi sınıf parametresiz oluşturucunuzu çağırın ve ardından bağımlılık özelliklerini ayarlamak için parametreleri kullanın. Bunlar sınıfınız tarafından tanımlanan bağımlılık özellikleri veya temel sınıflardan devralınan bağımlılık özellikleri olabilir, ancak her iki durumda da aşağıdaki deseni kullanın:

public MyClass : SomeBaseClass {  
    public MyClass(object toSetProperty1) : this() {  
        // Class initialization NOT done by default.  
        // Then, set properties to values as passed in ctor parameters.  
        Property1 = toSetProperty1;  
    }  
}  

Temel imzalarla eşleşen varsayılan olmayan (kolaylık) oluşturucular

Temel oluşturucuyu aynı parametrelemeyle çağırmak yerine kendi sınıfınızın parametresiz oluşturucuyu yeniden çağırın. Temel başlatıcıyı çağırmayın; bunun yerine öğesini çağırmalısınız this(). Ardından, geçirilen parametreleri ilgili özellikleri ayarlamak için değer olarak kullanarak özgün oluşturucu davranışını yeniden oluşturun. Belirli parametrelerin ayarlamayı amaçladığı özellikleri belirleme yönergeleri için özgün temel oluşturucu belgelerini kullanın:

public MyClass : SomeBaseClass {  
    public MyClass(object toSetProperty1) : this() {  
        // Class initialization NOT done by default.  
        // Then, set properties to values as passed in ctor parameters.  
        Property1 = toSetProperty1;  
    }  
}  

Tüm imzalarla eşleşmelidir

Temel türün birden çok imzaya sahip olduğu durumlarda, diğer özellikleri ayarlamadan önce sınıf parametresiz oluşturucuyu çağırmak için önerilen deseni kullanan kendi oluşturucu uygulamanızla tüm olası imzaları kasıtlı olarak eşleştirmeniz gerekir.

SetValue ile bağımlılık özelliklerini ayarlama

Özellik ayarı kolaylığı için sarmalayıcıya sahip olmayan bir özellik ayarlayıp ile SetValuedeğerleri ayarladıysanız aynı desenler geçerlidir. Bu geçiş oluşturucu parametrelerine SetValue çağrılarınız da başlatma için sınıfının parametresiz oluşturucuyu çağırmalıdır.

Ayrıca bkz.