C# 是否可以自定义访问修饰符行为?

C# 是否可以自定义访问修饰符行为?,c#,.net,access-modifiers,C#,.net,Access Modifiers,我有一个winform应用程序,它由两个程序集组成:业务层和前端层。每个usercontrol(前端层)都与业务层的一个类相关,即CustomerUserControl使用Customer类 可编辑属性,即Customer.Name,具有公共设置器,以便可以通过前端控件修改其值 我的问题是:是否可以更改属性的setter可访问性,使其仅对特定类具有或多或少的限制。在我的示例中,Customer.Name setter将是内部的,前端控件无法访问它,但相应的控件CustomerUserContro

我有一个winform应用程序,它由两个程序集组成:业务层和前端层。每个usercontrol(前端层)都与业务层的一个类相关,即CustomerUserControl使用Customer类

可编辑属性,即Customer.Name,具有公共设置器,以便可以通过前端控件修改其值

我的问题是:是否可以更改属性的setter可访问性,使其仅对特定类具有或多或少的限制。在我的示例中,Customer.Name setter将是内部的,前端控件无法访问它,但相应的控件CustomerUserControl可以访问它。否则,setter将是公共的,但除CustomerUserControl之外的控件无法访问


是否可以实现这种自定义访问权限?

您可以像这样限制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仍然可以假装是CustomerUserControl
SetName(new CustomerUserControl(),“newName”)
@Olivier Jacot Descombes-是的,它可以,我在回答中明确提到了这一点。你错过了吗?@EstericScreenName:对不起,我把注意力集中在代码上了。请参阅我答案的编辑。在这里,业务层并不依赖于UI层。ICCustomerNameProvider将在业务层程序集或合同程序集中声明。