2014-09-18 20 views
5

Hãy tưởng tượng bạn có một lớp được định nghĩa như sau.C# Tài liệu tham khảo; Giữ thành viên Thành viên ẩn danh

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

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

Tôi cần lớp người quản lý của mình bằng cách nào đó có thể thay đổi tham chiếu đã đặt cho thành viên SpecialData. Tôi có thể làm điều này với một con trỏ đôi hoặc bạn bè lớp trong C + +, nhưng tùy chọn đó không có sẵn trong C#, thật đáng buồn. Làm thế nào để giữ cho SpecialData được bảo vệ khỏi những người dùng bên ngoài thiết lập nó, trong khi vẫn cho phép lớp Manager kiểm soát thiết lập? Tôi có thể làm điều này với từ khóa nội bộ, nhưng điều đó dường như không vô cùng an toàn hay sạch ...

Any help is appreciated rất nhiều.

+2

Bạn có thể giải thích lý do tại sao bạn cho rằng 'nội bộ' không an toàn hoặc không sạch? Bạn có nghĩa là nó là như vậy nói chung, hoặc là bạn cho thấy nó không phù hợp với thiết kế cụ thể của bạn? Tôi có thể nói đây là một giải pháp hoàn hảo ở đây, mặc dù sự thật được bảo rằng tôi không chắc chắn tại sao bạn muốn làm điều này ngay từ đầu. – decPL

Trả lời

4

Nếu lớp quản lý là một phần của lắp ráp giống như SomeClass, làm cho thành viên internal sẽ làm cho nó có thể cho các lớp học trong cùng một assembly để truy cập setter:

public SpecialData data { get; protected internal set; } 

này cũng tương tự như sử dụng friend trong C++, với ngoại lệ là "tình bạn" được mở rộng cho tất cả các thành viên của cùng một hội đồng.

Nếu người quản lý là một phần của một gói phần mềm khác nhau, bạn có thể sử dụng InternalsVisibleTo thuộc tính về lắp ráp của bạn. Trong trường hợp này, tuy nhiên, bạn nên ký tên vào assembly mà bạn mở rộng tình bạn để tránh những nỗ lực truy cập vào setter từ mã không được phép.

+0

Tôi đã đề cập đến từ khóa nội bộ. Tôi nhận ra đó là một lựa chọn, nhưng nó là một lựa chọn tốt? Tôi đã lo lắng rằng ai đó có thể là một lỗi thiết kế. Nếu không, điều này chắc chắn sẽ hoạt động. Đây là một dự án lớn, vì vậy việc ghép nối chúng lại với nhau có thể là một vấn đề lớn ... – guitar80

+0

@ user3812869 Có, 'nội bộ' là một lựa chọn tốt. Nó được thiết kế cho các tình huống như thế này, khi bạn thiết kế một gói các lớp liên quan chia sẻ kiến ​​thức về biểu diễn bên trong. .NET có biện pháp phòng ngừa không để rò rỉ kiến ​​thức này bên ngoài thư viện của bạn. Có lẽ, không có cách nào để bảo vệ mã của bạn từ những người có thể sửa đổi lắp ráp của bạn. – dasblinkenlight

+0

Trong trường hợp đó, tôi sẽ cố gắng tìm ra các kinks. Thiết kế dường như hơi lạ với tôi. Trong thực tế, tôi có một StateManager và một Sprite chứa trong một đối tượng game. StateManager chứa các quốc gia. Các tiểu bang này cần chỉnh sửa trường Sprite. – guitar80

1

Tạo một lớp kế thừa SomeClass và trông loại này:

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

bảo vệ có nghĩa là nó có sẵn cho các dẫn xuất của lớp, và kể từ SomeClass không niêm phong, bạn chỉ có thể lấy được từ nó và làm bất cứ thứ gì bạn cần. Sau đó, bạn có thể sử dụng trình trang trí này thay vì bản thân số SomeClass. Và hơn nữa, bạn có thể có nhiều trang trí như bạn cần, mỗi xử lý đặc biệt của nó SpecialData.

1

Có thể không chính xác những gì bạn đang tìm kiếm, nhưng từ khóa internal được mô tả here có thể quản lý quyền truy cập trong cùng một cụm; có vẻ như một mục đích tương tự như từ khóa friend trong C++.

1

Bạn có thể làm cho tài sản internal. Điều đó sẽ làm cho thuộc tính chỉ hiển thị bên trong cùng một assembly. Tùy chọn bạn có thể sử dụng InternalsVisibleToAttribute để cho phép các hội đồng cụ thể truy cập vào thuộc tính đó.

Một cách khác là sử dụng một interface để che giấu tài sản đó:

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... 
} 

Bằng cách này, data là chỉ hiển thị từ tài liệu tham khảo giao diện.

Vì vậy, điều này không làm việc:

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

Nhưng điều này không:

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

gì về việc tạo ra một sự kiện trên lớp Manager, một cái gì đó giống như một sự kiện RequestChangeSpecialData. Các Manager bắn sự kiện này, và SomeClass sẽ thay đổi Ví dụ SpecialData.

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; 
    } 
} 

chưa được kiểm tra (viết bằng notepad)

Bây giờ Manager có thể thay đổi SpecialData tài sản. Bằng cách này, người quản lý không phụ thuộc vào SomeClass/giao diện hoặc lắp ráp.

+0

sắp sửa đăng tùy chọn sự kiện –

Các vấn đề liên quan