C# 是否可以自定义访问修饰符行为?
我有一个winform应用程序,它由两个程序集组成:业务层和前端层。每个usercontrol(前端层)都与业务层的一个类相关,即CustomerUserControl使用Customer类 可编辑属性,即Customer.Name,具有公共设置器,以便可以通过前端控件修改其值 我的问题是:是否可以更改属性的setter可访问性,使其仅对特定类具有或多或少的限制。在我的示例中,Customer.Name setter将是内部的,前端控件无法访问它,但相应的控件CustomerUserControl可以访问它。否则,setter将是公共的,但除CustomerUserControl之外的控件无法访问C# 是否可以自定义访问修饰符行为?,c#,.net,access-modifiers,C#,.net,Access Modifiers,我有一个winform应用程序,它由两个程序集组成:业务层和前端层。每个usercontrol(前端层)都与业务层的一个类相关,即CustomerUserControl使用Customer类 可编辑属性,即Customer.Name,具有公共设置器,以便可以通过前端控件修改其值 我的问题是:是否可以更改属性的setter可访问性,使其仅对特定类具有或多或少的限制。在我的示例中,Customer.Name setter将是内部的,前端控件无法访问它,但相应的控件CustomerUserContro
是否可以实现这种自定义访问权限?您可以像这样限制get或set访问器的范围:
//private set accessor - this is what you're looking for
public int SomeProperty { get; private set; }
//private get accessor
public int SomeOtherProperty { private get; set; }
cust.SetName(this);
我会使用setter的内部修饰符。这使得它只能在部件内部访问。如果CustomerUserControl位于另一个程序集中,则可以使用InternalsVisibleToAttribute
[assembly: InternalsVisibleTo("assembly name")]
编辑:你是对的。还有一种可能性:
声明一个接口,该接口将由允许设置名称的控件实现:
public interface ICustomerNameProvider
{
string CustomerName { get; }
}
在“客户添加方法”中:
public void SetName(ICustomerNameProvider customerNameProvider)
{
this.Name = customerNameProvider.CustomerName;
}
CustomerUserControl会这样调用它:
//private set accessor - this is what you're looking for
public int SomeProperty { get; private set; }
//private get accessor
public int SomeOtherProperty { private get; set; }
cust.SetName(this);
当然,这不是绝对可靠的,但意外地传递错误的控件将变得不可能。据我所知,无法将您所要求的直接应用于属性设置程序,因为它不知道调用从何处发起。但是,您可以使用mutator方法拼凑一些东西:
public class Customer
{
...
public string Name
{
get;
private set;
}
public void SetName(string callingControlName, string newName)
{
// you'd use TypeOf the same way to pass in callingControlName
if(TypeOf(this).Name + "UserControl" == callingControlName)
this.Name = newName;
}
...
}
请注意,这是一种荒谬的紧密耦合和糟糕的设计实践,但只要严格遵守问题中概述的命名约定(Customer
将1:1与CustomerUserControl
匹配),它就应该满足您的要求。顺便说一句,我并不是为了在可维护性方面获得一点改进而将callingControlName
与CustomerUserControl
进行静态比较,以防您想重命名CustomerUserControl类。同样需要注意的是,通过调用Customer.SetName(“CustomerUserControl”,“badName”)
可以很容易地消除这种情况。希望你不会把这件事透露给那些会做类似事情的程序员,但这是完全可能的
这里真正的问题是您的业务层不应该依赖于您的表示层。为什么需要将set访问限制到特定的UserControl?如果您确实需要(我想不出来)只从某个UI类访问业务属性的
集
,则需要对应用程序进行重大的重新设计。您是否考虑过不可变或可冻结的结构?请不要在标题前加上“C”。我们在这里使用标记。@asawyer:你是说传递一个元组吗?@jolySoft我想一个不可变的样式对象可能会完全避开这个问题。@Anne Christine:你为什么不接受一个答案,Oliver's是最完整的?这如何阻止另一个控件设置值?否决我,因为我否决了你,这有点违背了这个网站的原则。您是否错过了我答案中的私有集
部分?如何获取其中的值?公共设置其他属性的目的是什么?这两个属性之间的关系是什么?第一个属性有一个私有集
访问器,第二个属性有一个私有获取
访问器。它旨在显示您可以控制对属性的get和set访问器的访问。我首先包括了私有集
,因为OP就是这么要求的。问题是这个值是否可以由一个类和一个类设置。UI和业务对象之间的一对一映射。这就是我投票否决你的方式,因为你没有回答问题。不管怎样,正如我所说,谢谢你的时间。从这个问题来看,有两个程序集:业务和UI,所有的用户控件都在UI程序集中。这不会阻止ProductUserControl访问Customer.Name+1的setter,编辑后的答案是从我发布的内容中提高了设计质量。只需确保将接口放在第三个单独的程序集中,以避免循环引用。ProductUserControl仍然可以假装是CustomerUserControlSetName(new CustomerUserControl(),“newName”)
@Olivier Jacot Descombes-是的,它可以,我在回答中明确提到了这一点。你错过了吗?@EstericScreenName:对不起,我把注意力集中在代码上了。请参阅我答案的编辑。在这里,业务层并不依赖于UI层。ICCustomerNameProvider将在业务层程序集或合同程序集中声明。