2014-09-18 22 views
5

Aşağıdaki şekilde tanımlanmış bir sınıfınız olduğunu hayal edin.C# Referanslar; Üyeleri Gizlemek

public class SomeClass 
{ 
    public Manager m { get; protected set; } 
    public SpecialData data { get; protected set; } 

    //More methods and member code here... 
} 

Özel sınıf üyesine ait ayar referansını bir şekilde değiştirebilmek için yönetici sınıfıma ihtiyacım var. Bunu, C++ 'daki çift işaretçi veya arkadaş sınıfları ile yapabilirdim, ancak bu seçenek C#' da ne yazık ki mevcut değil. SpecialData'nın dıştaki kullanıcılardan korunmasını nasıl ayarlayabilirim, yine de yönetici sınıfının ayar üzerinde kontrolüne izin veriyor mu? Bunu dahili anahtar kelime ile yapabilirdim, ama bu inanılmaz derecede güvenli veya temiz görünmüyor ...

Herhangi bir yardım büyük beğeni topluyor.

+2

Neden "iç" in güvensiz veya kirli olduğuna inandığınızı açıklar mısınız? Genel olarak böyle olduğunu mu söylüyorsun yoksa özel tasarımın için uygun olmadığını mı söylüyorsun? Burada mükemmel bir çözüm olduğunu söyleyebilirim, gerçeği söylemek gerekirse neden bunu ilk etapta yapmak istediğinizden emin değilim. – decPL

cevap

4

müdür sınıfı üyesi haline SomeClass aynı grubunun bir parçası olan internal ayarlayıcı erişmek için aynı mecliste sınıflar için mümkün kılacak olursa:

public SpecialData data { get; protected internal set; } 

Bu içinde friend kullanmaya benzer C++, "arkadaşlığın" aynı meclisin tüm üyelerine uzatılması istisnasıyla.

Yönetici farklı bir paketin parçasıysa, derlemenizde InternalsVisibleTo özniteliğini kullanabilirsiniz. Ancak bu durumda, yetkisiz bir koddan setter'e erişim elde etme girişimlerini önlemek için arkadaşlığı genişletme mecburiyetini imzalamanız gerekir.

+0

Dahili anahtar kelimeden bahsetmiştim. Bunun bir seçenek olduğunu anlıyorum, ama bu iyi mi? Birinin tasarım hatası olabileceğinden endişeliydim. Değilse, bu kesinlikle işe yarar. Bu büyük bir projedir, bu yüzden bunları bir araya getirmek büyük bir sorun olabilir ... – guitar80

+0

@ user3812869 Evet, 'internal' iyi bir seçenektir. İç temsil bilgisini paylaşan ilgili sınıflardan oluşan bir paket tasarladığınızda, bu gibi durumlar için tasarlanmıştır. .NET, bu bilgiyi kitaplığınızın dışına sızmamaya yönelik önlemler alır. Muhtemelen, kodunuzu derlemenizi değiştirebilecek kişilerden korumanın bir yolu yoktur. – dasblinkenlight

+0

Bu durumda, kıvrımları çözmeye çalışacağım. Tasarım bana biraz garip geliyor. Gerçekte bir oyun nesnesinde bulunan bir StateManager ve Sprite var. StateManager, Devletler içerir. Bu Devletler Sprite alanını düzenlemelidir. – guitar80

1

SomeClass devralır ve bu tür görünen bir sınıf oluşturun: Korunan

internal class SomeClassDecorator : SomeClass 
{ 
    public void SetSpecialData(SpecialData value) 
    { 
     data = value; 
    } 
} 

o sınıfın türevlerine kullanılabilir ve SomeClass mühürlü olmadığı için, ondan türetmek ve yapılacak basitçe anlamına gelir İhtiyacın olan her şey. Daha sonra bu dekoratör SomeClass yerine kullanabilirsiniz. Üstelik, her biri özel SpecialData'u kullanarak ihtiyaç duyduğunuz kadar dekora sahip olabilirsiniz.

1

Tam aradığınız ancak internal kelime aynı derlemenin içinde erişimi yöneten edebilirsiniz here nitelendirdiği olmayabilir; C++ 'da friend anahtar sözcüğü ile benzer bir amaç gibi görünüyor. internal.

1

. Bu, mülkün yalnızca aynı montajın içinde görünmesini sağlayacaktır. İsteğe bağlı olarak, belirli derlemeler bu özelliğe erişime izin vermek için InternalsVisibleToAttribute kullanabilirsiniz.

diğer bir yaklaşım, özellik gizlemek için bir interface kullanımıdır:

public interface ISomeClass 
{ 
    Manager m { get; } 
    SpecialData data { get; set; } 
} 

public class SomeClass : ISomeClass 
{ 
    public Manager m { get; protected set; } 
    SpecialData ISomeClass.data { get; set; } 

    //More methods and member code here... 
} 

Bu şekilde, data arayüz referanstan görülebilir.

Yani bu işe yaramazsa:

SomeClass c = new SomeClass(); 
c.data; 

Ama bunu yapar:

ISomeClass c = new SomeClass(); 
c.data; 
3

Ne, Manager sınıfı bir RequestChangeSpecialData olay gibi bir şey bir olayı oluşturma hakkında. Manager, olayı tetikler ve SomeClass, SpecialData örneğini değiştirir.Denenmemiş

public class SomeClass 
{ 
    private Manager _m; 

    public Manager M 
    { 
     get { return _m} 
     set 
     { 
      // register/unregister event on property assignment 
      if(_m != null) 
       _m.RequestChangeSpecialData -= RequestChangeSpecialData; 

      _m = value; 

      if(_m != null) 
       _m.RequestChangeSpecialData += RequestChangeSpecialData; 

     } 
    } 

    public SpecialData Data { get; private set; } 

    private void RequestChangeSpecialData(object sender, ChangeSpecialDataEventArgs e) 
    { 
     // set the new reference 
     Data = e.SpecialData; 
    } 

} 

public class Manager 
{ 
    public void DoSomething() 
    { 
     // the manager class wants to do something, and wants to change the SpecialData instance.., so it fires the event RequestChangeSpecialData 


     SpecialData data = new SpecialData(); 

     // if the event is bound. 
     if(RequestChangeSpecialData != null) 
      RequestChangeSpecialData(this, new ChangeSpecialDataEventArgs(data)); 
    } 

    public event EventHandler<ChangeSpecialDataEventArgs> RequestChangeSpecialData; 
} 

public class ChangeSpecialDataEventArgs : EventArgs 
{ 
    public SpecialData Data {get; private set; } 

    public ChangeSpecialDataEventArgs(SpecialData Data) 
    { 
     Data = data; 
    } 
} 

Şimdi ManagerSpecialData özelliğini değiştirmek yapabiliyor (not defteri yazdı). Bu şekilde yönetici SomeClass/arabiriminden veya montajından bağımsız değildir.

+0

etkinlik seçeneği göndermek üzereydi –