Click here to Skip to main content
15,906,567 members
Please Sign up or sign in to vote.
4.67/5 (3 votes)
See more:
Hi, I have problem when trying to create property. Here's the example
public class Debt //Tanpa constructor
{
    [Description("This is readonly property"), ReadOnly(true)]
    public bool IsAccountLocked
    {
        get;
        set;
    }
}

public class Credit
{
    //Only get from this class and can not set value of IsAccountLocked
    Debt debt = new Debt();
    public string GetAccountName
    {
        get
        {
            if (debt.IsAccountLocked)
                return string.Empty;
            else
                return "CFX001";
        }
    }
}

public class UserAccounts
{
    //Only set from this class and can not get value os IsAccountLocked
    Debt debt = new Debt();
    internal void SetLock(string Account)
    {
        debt.IsAccountLocked = true;
    }
}


I have 3 classes. Debt, Credit and UserAcconts. In Debt there's a boolean property called IsAccountLocked. How to make this property can only be "GET" from Credit and only be "SET" from UserAccounts? In other words, if Credit tries to SET the property it generates error. Can I also hide "SET" from Credit. Thanks in advance.
Posted

You can't.
The only thing you can do is change the access modifiers to internal or protected, but you can't set an modifier depending on the type of the calling class. I.e. You can't have a getter that is private or internal in one class, and public in another - there is no mechanism for that in C#

You could probably do it at run time via reflection and the call stack, but that is a hairy way to do things.

Myself, I would probably create an abstract base class with protected getter and setter then derive two classes from that - one with a public getter, and one with a public setter.

It's a nasty idea though, as far as maintenance goes - it would need a good standard of commenting.
 
Share this answer
 
Comments
derodevil 30-Jul-12 10:03am    
Your solution makes sense. Unfortunately, in my project the Debt class is EventArguments inherits EventArgs. I dont' think I can create base class with some derived classes.
OriginalGriff 30-Jul-12 10:09am    
Yes you can!
public abstract class myClass : EventArgs
{
}
public class myClassChild : myClass
{
}
derodevil 30-Jul-12 10:39am    
Thank you for you explanation and solution. I'm now using your solution in my project. I accept it.
OriginalGriff 30-Jul-12 10:46am    
You're welcome!
Sergey Alexandrovich Kryukov 30-Jul-12 19:26pm    
Not exactly so. It is possible if you distribute the code in two separate assembly and use internal access. Please see my answer.
--SA
I don't think there is a language construct in c# to do this. I see two approaches:
1) Pass caller to the methods, and check type in the method.
A) Separating methods
C#
public class Debt //Tanpa constructor
    {
        private bool _IsAccountLocked;
        public void setIsAccountLocked(object caller, bool value)
        {
           if(!caller is UserAccounts)
           {
              throw new Exception("Only a UserAccount instance can set this");
           }
           _IsAccountLocked = value;
        }

        public bool IsAccountLocked
        {
           get { return _IsAccountLocked; }
        }
    }


B) Indexed property (khmmm...)
C#
public class Debt //Tanpa constructor
    {
        private bool _IsAccountLocked;
        public bool IsAccountLocked[object caller]
        {
           get { return _IsAccountLocked; }
           set {
             if(!caller is UserAccounts)
             {
                throw new Exception("Only a UserAccount instance can set this");
             }
             _IsAccountLocked = value;
           }
        }
    }

In both cases, the caller should pass this for the caller parameter.
2) If you can't trust the caller, you can get the calling class from the stack:
http://www.techdreams.org/microsoft/c-how-to-get-calling-class-name-method-name-using-stackframe-class/5815-20110507[^]
 
Share this answer
 
Comments
derodevil 30-Jul-12 10:07am    
I think these can't be implemented (public bool IsAccountLocked[object caller]). Do you have an idea if I want to hide setter and getter from specific class?
Zoltán Zörgő 30-Jul-12 13:35pm    
Might be, never tried :). You can not grant access rights on methods to classes - although this could make sense only in distributed applications. But this alone would not secure. And Griff's solution you accepted can also be broken with reflection.
Sergey Alexandrovich Kryukov 30-Jul-12 19:26pm    
Not exactly so. It is possible if you distribute the code in two separate assembly and use internal access. Please see my answer.
--SA
Despite Solution 1 and Solution 2 tells you that this is not possible, there is a way to do it, but then you need to put the classes in two different assemblies.

Assembly #1:
C#
public class Debt {
    //...
    internal bool IsAccountLocked { get; set; } // internal allows access by the type of the same assembly...
    //...
}

public class UserAccounts { /* ... */ } //...so, Debt.IsAccountLocked is accessible here


Assembly #2:
C#
public class Credit { /* ... */ } //Debt.IsAccountLocked is not accessible, because this is a different assembly


[EDIT]

It is strictly impossible to achieve the same effect on the property access if you try to do it in a single assembly.

—SA
 
Share this answer
 
v2
Comments
derodevil 30-Jul-12 22:00pm    
I also tried your solution and it's pretty good if I develop large project. What I want here is a simpler way in a single assembly. Thank you for helping me. I appreciate it so much.
Sergey Alexandrovich Kryukov 30-Jul-12 22:07pm    
You are welcome.

I think you should accept this answer formally (green button), even if it does not fit your purpose perfectly. You received quite complete analysis if this issue; the other method of access restriction to your requirement does not exist, which is, by the way, confirmed by the authors of other solutions.
--SA
Sergey Alexandrovich Kryukov 30-Jul-12 22:09pm    
...to make it more clear, I added an update to my answer, please see, after [EDIT].
--SA
derodevil 31-Jul-12 7:59am    
That's quite clear I think. I also use your solution in my other project. By the way, I'll have to compare which is the best for me in my next project. Many thanks for helping me.
Sergey Alexandrovich Kryukov 31-Jul-12 11:22am    
You are very welcome. I really appreciate your desire to be as precise as possible in access, and I hope -- in all other aspects. I've up-voted you question with my 5.
Good luck, call again.
--SA

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900