I want to make properties of an object readonly, except for certain classes that I want to allow access to change property values. How do I do this?
我希望只读取一个对象的属性,除了我想允许访问更改属性值的某些类。我该怎么做呢?
class Restricted ()
{
public int Property1{get; }
public int Property2{get; }
}
If I do :
如果我做 :
public int Property1{ get; private set;}
How can I choose which class to allow to set this property? check typeof? Is this a valid approach ans secure?
如何选择允许设置此属性的类?检查typeof?这是一种有效的方法吗?
5 个解决方案
#1
You can create friend assemblies. That is, give access to internal methods of your class to all the classes in another assembly. I don't think you can do it on a class-by-class basis.
您可以创建好友程序集。也就是说,允许访问类的内部方法到另一个程序集中的所有类。我不认为你可以逐类进行。
#2
You can't, at least not using the language alone. The access modifiers in C# are:
你不能,至少不单独使用这种语言。 C#中的访问修饰符是:
- public: anyone can set the property
- private: only code in this class can set the property
- protected: only code in this class or subclasses can set the property
- internal: only code in this assembly (or InternalsVisibleTo assemblies) can set the property
- protected internal: only code in this class or subclasses, or in this assembly (or InternalsVisibleTo assemblies), can set the property
public:任何人都可以设置该属性
private:此类中只有代码可以设置属性
protected:只有此类或子类中的代码才能设置该属性
internal:只有此程序集中的代码(或InternalsVisibleTo程序集)才能设置该属性
protected internal:只有此类或子类中的代码,或者此程序集(或InternalsVisibleTo程序集)中的代码才能设置属性
There's no modifier for "specific classes can set the property" similar to friend declarations in C++.
“特定类可以设置属性”没有类似于C ++中的友元声明的修饰符。
#3
If you control the classes that you want to give access to the setter, you could mark the property's set as "internal" and then compile all your classes into the same assembly. This way, anything else that's using your class won't be able to use the setter.
如果您控制要授予setter访问权限的类,则可以将属性的设置标记为“internal”,然后将所有类编译到同一个程序集中。这样,使用你的类的任何其他东西都将无法使用setter。
#4
Use an interface in general which only allows read access.
通常使用只允许读访问的接口。
public interface IPublicProperties
{
int Property1 { get; }
int Property2 { get; }
}
internal class Restricted : IPublicProperties
{
public int Property1 { get; set; }
public int Property2 { get; set; }
}
The downside is, the class using the setters needs to cast the interface to the actual class. The good thing is, in most of the cases there are benefits of using interfaces in the long run.
缺点是,使用setter的类需要将接口强制转换为实际的类。好处是,在大多数情况下,长期使用接口都有好处。
#5
These ways work in C++, without using the friend
access specifier. I'm not sure if they'll work in C#. also, this is just off the top of my head, after seeing your question after a long day, so it may be riddled with errors.
这些方法适用于C ++,而不使用友元访问说明符。我不确定他们是否会在C#中工作。此外,经过漫长的一天看到你的问题之后,这只是我的头脑,所以它可能充满了错误。
One way: the class casts itself to a private base in which the members are mutable. Drawback: any other class can call unlock.
一种方式:该类将自己投射到成员可变的私人基地。缺点:任何其他类都可以调用解锁。
#include <iostream>
struct unlocked {
int a;
int b;
//virtual ~unlocked(); // don't call delete on a unlocked
};
class locked : private unlocked {
public:
locked() {
a = 0 ; // accessible within locked
b = 1 ;
}
unlocked& unlock( ) {
return *this ;
}
void print( std::ostream& o ) {
o << " a = " << a << ", b = " << b << std::endl ;
}
} ;
Usage:
int main() {
locked foo ;
foo.print( std::cout );
// foo.a = 1 ; illegal
foo.unlock().a = 1 ;
foo.print( std::cout ) ;
std::cout << &foo << " " << &(foo.unlock()) << std::endl;
}
Another way: to call unlock, an instance of a class key' must be passed. Class
keyis a protected inner class of public class 'keyed'. Only class
keyedcan mutate class 'locked
. Drawback: locked
must privately inherit keyed
, to make keyed::key
visible to locked
. But because both keyed
and key
have no members, inheriting from them has little overhead. You can use keyed
as is, or better, inherit from it.
另一种方式:调用unlock,必须传递一个类密钥的实例。 Classkey是一个受保护的公共类内部类'keyed'。只有classkeyed可以改变类'锁定。缺点:锁定必须私有继承keyed,使keyed :: key可见锁定。但是因为keyed和key都没有成员,所以继承它们的开销很小。您可以按原样使用keyed,或者更好地继承它。
#include <iostream>
class locked ;
class keyed ;
class keyed {
protected:
struct key{};
public:
void mutateLocked( locked& );
};
struct unlocked {
int a;
int b;
void print( std::ostream& o ) {
o << this << " a = " << a << ", b = " << b << std::endl ;
}
};
class locked : private unlocked, private keyed {
public:
locked() {
a = 0 ;
b = 1 ;
}
unlocked& unlock( keyed::key& k) {
return *this ;
}
using unlocked::print;
} ;
void keyed::mutateLocked(locked& m ) {
key k ;
m.print(std::cout) ;
unlocked& n = m.unlock( k ) ;
n.a = 55;
n.b = 77;
n.print(std::cout);
}
Usage:
int main() {
keyed k ;
//keyed::key kk; // not accessible
locked foo ;
//unlocked& bar = (unlocked) foo; // not accessible
foo.print( std::cout );
//foo.a = 1 ; // not accessible
//foo.unlock(kk).a = 1 ;
k.mutateLocked(foo);
foo.print( std::cout ) ;
}
#1
You can create friend assemblies. That is, give access to internal methods of your class to all the classes in another assembly. I don't think you can do it on a class-by-class basis.
您可以创建好友程序集。也就是说,允许访问类的内部方法到另一个程序集中的所有类。我不认为你可以逐类进行。
#2
You can't, at least not using the language alone. The access modifiers in C# are:
你不能,至少不单独使用这种语言。 C#中的访问修饰符是:
- public: anyone can set the property
- private: only code in this class can set the property
- protected: only code in this class or subclasses can set the property
- internal: only code in this assembly (or InternalsVisibleTo assemblies) can set the property
- protected internal: only code in this class or subclasses, or in this assembly (or InternalsVisibleTo assemblies), can set the property
public:任何人都可以设置该属性
private:此类中只有代码可以设置属性
protected:只有此类或子类中的代码才能设置该属性
internal:只有此程序集中的代码(或InternalsVisibleTo程序集)才能设置该属性
protected internal:只有此类或子类中的代码,或者此程序集(或InternalsVisibleTo程序集)中的代码才能设置属性
There's no modifier for "specific classes can set the property" similar to friend declarations in C++.
“特定类可以设置属性”没有类似于C ++中的友元声明的修饰符。
#3
If you control the classes that you want to give access to the setter, you could mark the property's set as "internal" and then compile all your classes into the same assembly. This way, anything else that's using your class won't be able to use the setter.
如果您控制要授予setter访问权限的类,则可以将属性的设置标记为“internal”,然后将所有类编译到同一个程序集中。这样,使用你的类的任何其他东西都将无法使用setter。
#4
Use an interface in general which only allows read access.
通常使用只允许读访问的接口。
public interface IPublicProperties
{
int Property1 { get; }
int Property2 { get; }
}
internal class Restricted : IPublicProperties
{
public int Property1 { get; set; }
public int Property2 { get; set; }
}
The downside is, the class using the setters needs to cast the interface to the actual class. The good thing is, in most of the cases there are benefits of using interfaces in the long run.
缺点是,使用setter的类需要将接口强制转换为实际的类。好处是,在大多数情况下,长期使用接口都有好处。
#5
These ways work in C++, without using the friend
access specifier. I'm not sure if they'll work in C#. also, this is just off the top of my head, after seeing your question after a long day, so it may be riddled with errors.
这些方法适用于C ++,而不使用友元访问说明符。我不确定他们是否会在C#中工作。此外,经过漫长的一天看到你的问题之后,这只是我的头脑,所以它可能充满了错误。
One way: the class casts itself to a private base in which the members are mutable. Drawback: any other class can call unlock.
一种方式:该类将自己投射到成员可变的私人基地。缺点:任何其他类都可以调用解锁。
#include <iostream>
struct unlocked {
int a;
int b;
//virtual ~unlocked(); // don't call delete on a unlocked
};
class locked : private unlocked {
public:
locked() {
a = 0 ; // accessible within locked
b = 1 ;
}
unlocked& unlock( ) {
return *this ;
}
void print( std::ostream& o ) {
o << " a = " << a << ", b = " << b << std::endl ;
}
} ;
Usage:
int main() {
locked foo ;
foo.print( std::cout );
// foo.a = 1 ; illegal
foo.unlock().a = 1 ;
foo.print( std::cout ) ;
std::cout << &foo << " " << &(foo.unlock()) << std::endl;
}
Another way: to call unlock, an instance of a class key' must be passed. Class
keyis a protected inner class of public class 'keyed'. Only class
keyedcan mutate class 'locked
. Drawback: locked
must privately inherit keyed
, to make keyed::key
visible to locked
. But because both keyed
and key
have no members, inheriting from them has little overhead. You can use keyed
as is, or better, inherit from it.
另一种方式:调用unlock,必须传递一个类密钥的实例。 Classkey是一个受保护的公共类内部类'keyed'。只有classkeyed可以改变类'锁定。缺点:锁定必须私有继承keyed,使keyed :: key可见锁定。但是因为keyed和key都没有成员,所以继承它们的开销很小。您可以按原样使用keyed,或者更好地继承它。
#include <iostream>
class locked ;
class keyed ;
class keyed {
protected:
struct key{};
public:
void mutateLocked( locked& );
};
struct unlocked {
int a;
int b;
void print( std::ostream& o ) {
o << this << " a = " << a << ", b = " << b << std::endl ;
}
};
class locked : private unlocked, private keyed {
public:
locked() {
a = 0 ;
b = 1 ;
}
unlocked& unlock( keyed::key& k) {
return *this ;
}
using unlocked::print;
} ;
void keyed::mutateLocked(locked& m ) {
key k ;
m.print(std::cout) ;
unlocked& n = m.unlock( k ) ;
n.a = 55;
n.b = 77;
n.print(std::cout);
}
Usage:
int main() {
keyed k ;
//keyed::key kk; // not accessible
locked foo ;
//unlocked& bar = (unlocked) foo; // not accessible
foo.print( std::cout );
//foo.a = 1 ; // not accessible
//foo.unlock(kk).a = 1 ;
k.mutateLocked(foo);
foo.print( std::cout ) ;
}