繁体   English   中英

C#限制使用类

[英]C# restricting use of a class

下面的代码完成了我想做的事情。 Main方法中的代码外观和行为完全符合要求。 但是,如果Userer,Home和DropdownMenu2类只能由HeaderNavigationMenu使用,则可以防止其他开发人员尝试在HeaderNavigationMenu类之外使用它们,这将是更好的选择。 此外,大多数文章都不愿公开所有内容。

问题 :在以下情况下使用的设计模式是否适当?在这种情况下是否有更好,更可接受的使用方式?


编辑:这种设计的原因。

  1. 我希望HeaderNavigationMenu的最终用户仅能够使用点表示法来获取可用选项的列表。 该体系结构实现了此目标(例如:navigationMenu.DropdownMenu2.SelectOption3())
  2. 希望其他最终需要编辑代码的人了解类UserMenu,Home和DropDownMenu2,这些类是专门由HeaderNavigationMenu类实现的。

public class HeaderNavigationMenu
{
    public HeaderNavigationMenu()
    {
        UsersMenu = new UsersMenu();
        Home = new Home();
        DropdownMenu2 = new DropdownMenu2();
    }

    public UsersMenu UsersMenu { get; set; }
    public Home Home { get; set; }
    public DropdownMenu2 DropdownMenu2 { get; set; }
}

public class UsersMenu
{
  ...
}

public class Home
{
  ...
}

public class DropdownMenu2
{
  public void SelectOption3()
  {
    ...
  }
  ...
}

static void Main(string[] args)
{
  HeaderNavigationMenu navigationMenu = new HeaderNavigationMenu();
  navigationMenu.DropdownMenu2.SelectOption3();

  // The following code is an example of undesired capability; 
  // prefer if Home class could only be 
  // used by HeaderNavigationMenu class
  Home home = new Home();
}

限制对类构造函数的访问。 如果将它们声明为“内部”,则这些类只能由您的代码创建。

如果您正在寻找抵御的实例UsersMenuDropdownMenu2Home从外部HeaderNavigationMenu但仍然是相同的项目作为内HeaderNavigationMenu然后有一个巧妙的方法,可以实现这种行为。 您可以将公共嵌套类与私有构造函数一起使用,这些私有构造函数会静态初始化其自己的工厂方法。 基本模板如下:

public class Outer{
  private static Func<Inner> _innerFactory;
  public Inner ExposedInner {get; private set;}

  public Outer(){
    // Force the static initializer to run.
    System.Runtime.CompilerServices.RuntimeHelpers.RunClassConstructor(typeof(Inner).TypeHandle);

    // Call the newly created factory method instead of a regular constructor.
    ExposedInner = _innerFactory();
  }

  public class Inner {
    static Inner(){
      // Initialize Outer's static factory method.
      _innerFactory = () => new Inner();
    }

    // Inner cannot be instantiated (without reflection) because its constructor is private.
    private Inner(){}

    // This method is now exposed for anyone to use.
    public void DoStuff(){ Console.WriteLine("Did stuff"); }
  }
}

这是您的示例中实现的概念:

class Program
{
    static void Main(string[] args)
    {
        HeaderNavigationMenu navigationMenu = new HeaderNavigationMenu();
        navigationMenu.DropdownMenu2.SelectOption3();

        // This line will no longer work because the constructors
        // for the inner classes are private.
        HeaderNavigationMenu.HomeImpl home = new HeaderNavigationMenu.HomeImpl();

        Console.ReadKey();
    }
}

public class HeaderNavigationMenu
{
    //Private factory methods that are statically initialized
    private static Func<UsersMenuImpl> _createUsers;
    private static Func<DropdownMenu2Impl> _createDropdown;
    private static Func<HomeImpl> _createHome;

    public HeaderNavigationMenu()
    {
        //Force the static constructors to run
        System.Runtime.CompilerServices.RuntimeHelpers.RunClassConstructor(typeof(UsersMenuImpl).TypeHandle);
        System.Runtime.CompilerServices.RuntimeHelpers.RunClassConstructor(typeof(HomeImpl).TypeHandle);
        System.Runtime.CompilerServices.RuntimeHelpers.RunClassConstructor(typeof(DropdownMenu2Impl).TypeHandle);

        UsersMenu = _createUsers();
        Home = _createHome();
        DropdownMenu2 = _createDropdown();
    }

    public UsersMenuImpl UsersMenu { get; set; }
    public HomeImpl Home { get; set; }
    public DropdownMenu2Impl DropdownMenu2 { get; set; }

    public class UsersMenuImpl
    {
        //Static constructor to make the class factory method
        static UsersMenuImpl()
        {
            _createUsers = () => new UsersMenuImpl();
        }

        private UsersMenuImpl() { }
    }

    public class HomeImpl
    {
        //Static constructor to make the class factory method
        static HomeImpl()
        {
            _createHome = () => new HomeImpl();
        }

        private HomeImpl() { }
    }

    public class DropdownMenu2Impl
    {
        //Static constructor to make the class factory method
        static DropdownMenu2Impl()
        {
            _createDropdown = () => new DropdownMenu2Impl();
        }

        private DropdownMenu2Impl() { }

        public void SelectOption3()
        {
        }
    }
}

这样,您仍然可以使用内部类的所有公共属性,但是没有人可以从HeaderNavigationMenu外部实例化内部类,只有HeaderNavigationMenu可以访问工厂方法。

我真的不明白你的使用情况是什么,我从来没有编码这样的,但只露出所需的行为的一种方式HeaderNavigationMenu是使类内部和私有变量,然后仅露出SelectOption3()方法, 如下。

如果您取消注释该行

//Home home = new Home();

您将得到一个编译器错误。

class Program
{
    static void Main(string[] args)
    {
        HeaderNavigationMenu navigationMenu = new HeaderNavigationMenu();
        navigationMenu.DropdownMenu2SelectOption3();

        // The following code is an example of undesired capability; 
        // prefer if Home class could only be 
        // used by HeaderNavigationMenu class
        //Home home = new Home();
    }
}
public class HeaderNavigationMenu
{
    UsersMenu usersMenu;
    Home home;
    DropdownMenu2 dropdownMenu2;

    public HeaderNavigationMenu()
    {
        usersMenu = new UsersMenu();
        home = new Home();
        dropdownMenu2 = new DropdownMenu2();
    }

    public void DropdownMenu2SelectOption3()
    {
        dropdownMenu2.SelectOption3();
    }

    class UsersMenu
    {
    }

    class Home
    {
    }

    class DropdownMenu2
    {
        public void SelectOption3()
        {
        }
    }
}

您可以将UsersMenuHomeDropdownMenu2 Home public abstract类。 然后将private类嵌套在HeaderNavigationMenu内部, HeaderNavigationMenu扩展public abstract版本。

public abstract class UsersMenu
{
}

public abstract class Home
{
}

public abstract class DropdownMenu2
{
   public void SelectOption3()
   {
      // Code for SelectOption3...
   }
}

public class HeaderNavigationMenu
{
    public HeaderNavigationMenu()
    {
        UsersMenu = new UsersMenuImpl();
        Home = new HomeImpl();
        DropdownMenu2 = new DropdownMenu2Impl();
    }

    public UsersMenu UsersMenu { get; }
    public Home Home { get; }
    public DropdownMenu2 DropdownMenu2 { get; }

    private class UsersMenuImpl : UsersMenu
    {
    }

    private class HomeImpl : Home
    {
    }

    private class DropdownMenu2Impl : DropdownMenu2
    {
    }
}

相同的开发人员可以查看和使用UsersMenuHomeDropdownMenu2 abstract类,但不能创建它们的实例。 只有HeaderNavigationMenu可以。

当然,另一位开发人员总是可以从public abstract类派生自己的类,但是您只能做很多事情。 UsersMenuHomeDropdownMenu2必须是public的才能成为public属性。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM