[.net] Accessing private field of class X from class Y

Started by
11 comments, last by mitchw 17 years, 11 months ago
I have a simple question, It it possible for class X (the kernel class) to access the private m_ProcessID field of class Y (the process class)? Something like friend classes of C++? Thanks in advance!
Advertisement
You can do this with reflection, but it's a bit cumbersome, so you might want to make a public (or internal) getter instead.

y.GetType().GetField("m_ProcessID", BindingFlags.Instance|BindingFlags.NonPublic).GetValue(y)
I can't use a public getter, because I want ONLY the kernel class to be able to set the m_ProcessID field.

I tried making m_ProcessID internal, but I can't seem to understand how it works. I can access Process.m_ProcessID from any class in the project.

Thanks for your help! I will try the snippet you posted.
Yes you CAN do it. You could make the field public, there are other ways also. But that is find of ruining the reason you put things in classes in the first place. As a general rule you should not allow direct access to members of another class. Make the access go through the class that has the member, this protects the data and the way you access it.

theTroll
Might be a good chance to use C# Properties. Basically they allow you to make data fields public, but still determine how they are accessed and mutated. I know it's not quite what you are looking for because the data isn't shared exclusively between two classes, but it's a lot safer than just declaring data members public.
One way to partition the access of a class is to use interfaces. So you'd have one interface that exposes what the kernel sees, and then one interface which exposes what everyone else can see. Then you just make sure that nobody access the class from but only the interfaces. So the kernel would have an object of type IKernelView and the others would use IOthersView (or something).

This is an unfortunate omission in C#, but I hardly think friends are the solution. Something like what Eiffel does (where each feature of class defines who it exposes itself to) would probably be ideal.
You can use Interfaces in C#, the syntax is just different.

theTroll
Quote:Original post by TheTroll
You can use Interfaces in C#, the syntax is just different.

theTroll


Yeah, but interfaces don't really solve the problem. What if another class casts the interface to the type of the base class? Then they could see and access everything public.

I think 'internal' is the best way to go. If you don't already know, internal makes it so only that assembly can access it. If you define your kernel and class Y in one project that is compiled to a .dll and your other code in another project in the same solution, then internal things in Y are visible to Kernel (and other classes in your 'framework/engine' project) but not to your main program.

A nice side effect is that it encourages you to split functionality into neat, well-defined blocks.
Quote:Original post by storage
I can't use a public getter, because I want ONLY the kernel class to be able to set the m_ProcessID field.

So? Just don't provide a setter:

public int ProcessID{   get{ return m_ProcessID; }}
--AnkhSVN - A Visual Studio .NET Addin for the Subversion version control system.[Project site] [IRC channel] [Blog]
Methods I can think of:

1. Reflection is one sure fire way to do it. It is cumbersome, but it is also the most straightforward.

BeerHunter provided sample code for accessing a field. This will let you access a property; the only real change is the BindingFlags used.

PropertyInfo propertyInfo = objectToSet.GetType().GetProperty("NameToSet",      BindingFlags.Instance | BindingFlags.GetProperty | BindingFlags.NonPublic);propertyInfo.SetValue(objectToSet, valueToSet);


2. Have the child contact the kernel for its process identifier using a callback routine. This allows the processing of the assignment to occur within the child, but lets the "friend" class have the last say. You could process the callback routine within the constructor.

3. Create a separate factory function inside the child class which is responsible for creating new child objects. Pass to the factory function the identifier that is to be assigned and allow the factory to produce the object. Since the factory is a part of the class it has access to all data in the class, private, protected, or public.

4. Wrap the field you're trying to set in an accessor. When the value is changed or attempted to be changed, take action. If the value isn't set yet, allow it to be set. If the value is set, perform authentication as necessary to verify that the value should be overridden. If necessary you can even examine the stack trace to determine what the calling objects are but be aware that release optimizations often change the stack trace; in debug mode it works flawlessly because inlining isn't performed, etc. In release mode four functions can be inlined in a row, giving you results which are not expected.

#2 seems to be the most stable and proper. It allows the process to retain contrl of when the identifier is changed, but it does remove the ability of the kernel from being able to change the process ID on the fly. This may be desired -- so this may not be a bad thing.

(I read your post as "access" being to change, read and write, not read only. Several solutions have been suggested above for read only access. Most of mine are more concerned with the kernel setting the process ID.)
..what we do will echo throughout eternity..

This topic is closed to new replies.

Advertisement