Links to C #; Member Storage

Imagine you have a class defined as follows.

public class SomeClass { public Manager m { get; protected set; } public SpecialData data { get; protected set; } //More methods and member code here... } 

I need my manager class to somehow change the given link for the SpecialData member. I could do this with two pointers or friend classes in C ++, but this option is not available in C #, unfortunately. How to keep SpecialData protected from external users by configuring it while maintaining control over the class of the Manager class? I could do this with an internal keyword, but that doesn't seem incredibly safe or clean ...

Any help is greatly appreciated.

+5
source share
5 answers

If the manager class is part of the same assembly as SomeClass , including the internal member will allow classes in the same assembly to access the installer:

 public SpecialData data { get; protected internal set; } 

This is similar to using friend in C ++, except that "friendship" applies to all members of the same assembly.

If the manager is part of another package, you can use the InternalsVisibleTo attribute of your assembly. In this case, however, you must sign the assembly to which you are expanding friendships to avoid trying to access the installer from unauthorized code.

+4
source

How to create an event in the Manager class, something like the RequestChangeSpecialData event. Manager fires the event, and SomeClass modifies the instance of 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; } } 

UNTESTED (written in notebook)

Manager can now change the SpecialData property. Thus, the manager is independent of SomeClass / interface or assembly.

+3
source

Create a class that inherits SomeClass and looks like this:

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

Protected means that it is available for derivatives of the class, and since SomeClass not sealed, you can simply extract from it and do whatever you need. Then you can use this decorator instead of SomeClass . And besides, you can have as many decorators as you need, each of which processes its own special SpecialData .

+1
source

This may not be exactly what you are looking for, but the internal keyword described here can control access within the same assembly; this seems like the same goal as the friend keyword in C ++.

+1
source

You can create an internal property. This will make the property visible only within the same assembly. You can optionally use InternalsVisibleToAttribute to allow specific assemblies access to this property.

Another approach is to use interface to hide this property:

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

Thus, data displayed only from a link to the interface.

So this does not work:

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

But it does:

 ISomeClass c = new SomeClass(); c.data; 
+1
source

Source: https://habr.com/ru/post/1202885/


All Articles