0

I am writing a class library to interface with a piece of test equipment through Ethernet commands. The device can have multiple axes defined. The main class will need to be able to send and receive commands. Also, each axis will need to be able to send and receive commands. Here is an example:

public class TestEquipment
{
    private TcpClient _tcpClient;
    private NetworkStream _networkStream;
    public Axis[] Axes; // Variable should be accessible publicly

    public TestEquipment()
    {
        Axes = new Axis[2];
        Axes[0] = new Axis();
        Axes[1] = new Axis();
    }

    public void Initialize()
    {
        // Use send/receive method to initialize the device
    }

    internal string SendReceive(string command)
    {
        return // Uses _tcpClient and _networkStream to talk to the device
    }

    internal class Axis
    {
        public double Angle
        {
            get
            {
                // Use send/receive method from parent class to get the axis angle
            }

            set
            {
                // Use send/receive method from parent class to set the axis angle
            }
        }
    }
}

Now I have two different problems. The first is that I have red squiggles under Axes for line public Axis[] Axes because Axis is less accessible than Axes. The second problem is that I am not sure how to use SendReceive from the TestEquipment class and its inner Axis class.

The Axes problem can be fixed if it is not nested and public, but I don't want any Axis to be created outside of TestEquipment.

I can use SendReceive in both classes if I put the method and the TcpClient and NetworkStream in a static class and make them static but that seems ugly.

Here is a quick snippet of how it is used:

var device = new TestEquipment();
device.Initialize();
device.Axes[0].Angle = 90;

These should NOT be possible outside of the TestEquipment class:

device.SendReceive("");
var newAxis = new Axis();

Unfortunately I am not able to share my actual code, so if needed, I can add on to my example code. If there is any more clarification needed I am happy to do so.

Answer

Here is the working code:

public class TestEquipment
{
    private TcpClient _tcpClient;
    private NetworkStream _networkStream;
    public Axis[] Axes;

    public TestEquipment()
    {
        Axes = new Axis[2];
        Axes[0] = new Axis(this);
        Axes[1] = new Axis(this);
    }

    public void Initialize()
    {
        // Use send/receive method to initialize the device
    }

    private string SendReceive(string command)
    {

    }

    public class Axis
    {
        private TestEquipment _parent;

        internal Axis(TestEquipment parent)
        {
            _parent = parent;
        }

        public double Angle
        {
            get
            {
                return _parent.SendReceive("");
            }

            set
            {
                value = _parent.SendReceive("");
            }
        }
    }
}
Alex
  • 870
  • 2
  • 9
  • 19
  • For the accessibility problem you could simple have a public interface for `Axis`, say `IAxis`, and define `Axes` as `public IAxis[] Axes;`. – Samir Aguiar Jan 13 '17 at 01:09
  • As for the other problem, you could have `Axis` receive an instace of `TestEquipment` in its constructor and have it set to a private property, and when constructing it you could do `new Axis(this)`. This way you could use the `send`/`receive` methods from that instance. – Samir Aguiar Jan 13 '17 at 01:13
  • Thank you @kopranb. My issue is now completely resolved. – Alex Jan 15 '17 at 18:18

1 Answers1

1

You seem to have the wrong impression of what internal does: it limits access to classes in the same Assembly, not the same class.

In order to prevent device.SendReceive(""); being possible outside TestEquipment, you need to make it private instead of internal.

For Axis, you can leave it nested (or not), but make it public, and give it an internal constructor:

public class Axis
{
    internal Axis() { }

    public double Angle { get; set; } // and so on
}

This stops C# from automatically generating a public parameterless constructor, and makes it so that Axis can only be constructed from within the Assembly.

There's no way to restrict it to only the outer class, unfortunately - although there are some workarounds, described in this question's answers: How to restrict access to nested class member to enclosing class?

Community
  • 1
  • 1
Blorgbeard
  • 101,031
  • 48
  • 228
  • 272
  • Thank you this fixed the problem for my Axis class. I didn't even think of setting the constructors accessor to internal. Unfortunately, this does not solve my SendReceive problem. I saw some other suggestions of what @kopranb said so I am going to give that a go. – Alex Jan 13 '17 at 15:40