Jump to content
  • Advertisement
Sign in to follow this  
storage

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

This topic is 4523 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

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!

Share this post


Link to post
Share on other sites
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)

Share this post


Link to post
Share on other sites
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.

Share this post


Link to post
Share on other sites
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

Share this post


Link to post
Share on other sites
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.

Share this post


Link to post
Share on other sites
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.

Share this post


Link to post
Share on other sites
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.

Share this post


Link to post
Share on other sites
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; }
}

Share this post


Link to post
Share on other sites
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.)

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!