簡體   English   中英

類訪問者級別 - 如何使這成為可能?

[英]Class accessor level - how to make this possible?

我有這種情況:我需要class2(string)構造函數只能從class1方法中訪問,而不是從外部類訪問:

public class class1 
{
    public void access() 
    { 
        //want to make class2(string) be accessible only from here
    }


    public class class2 
    {
        public class2() 
        { 
        }

        private class2(string p) 
        {   
        }
    }
}

我正在嘗試驗證用戶, class2()創建用戶類的空實例,而class2(...)登錄用戶。 現在我有class1登錄方法訪問,可以從我的頁面調用,我不希望我的任何頁面直接調用我的class2(...)登錄但必須從class1.access()傳遞,返回class2與用戶信息。

編輯:這樣做的目的是創建一個安全的登錄過程,我不想公開我的登錄並直接從我的頁面訪問它,我希望我的頁面從class1.access()的邏輯傳遞,這將考慮關於如何/如果登錄用戶並返回並清空class2如果登錄失敗,同時class2.valid=false; 或將返回包含用戶所有信息的class2 我需要從我的頁面訪問和創建並清空class2 ,因為我在class1.access(login_credentials credentials, out class2 user_data)它作為param傳遞out

據我所知,沒有直接的機制來限制對嵌套類的構造函數的訪問僅限於它的包裝類。 您可以考慮使用幾種代碼重新設計的解決方法。 如果您願意,可以將構造函數internal

public class class1 
{
    public void access() 
    { 
        var c = new class2("asdf");
    }

    public class class2 
    {
        public class2() 
        { 
        }

        internal class2(string p) 
        {   
        }
    }
}

這將限制對class2所在程序集的構造函數的訪問。 如果您只想限制使用庫的第三方訪問權限,那么這可能是一個可行的解決方案。

另一個選擇是你可以利用嵌套的class2可以訪問class1 private成員這一事實。 通過這種方式,您可以提升工廠方法來“公開”構造函數:

public class class1 
{
    private static Func<string, class2> CreateNewClass2;

    static class1()
    {
        //this just forces the static constructor on `class2` to run.
        System.Runtime.CompilerServices.RuntimeHelpers.RunClassConstructor(typeof(class2).TypeHandle);
    }

    public void access() 
    { 
        class2 c = CreateNewClass2("asdf");
    }

    public class class2 
    {
        static class2()
        {
            //this is where we create a delegate exposing/promoting our private constructor
            class1.CreateNewClass2 = p => new class2(p);
        }

        public class2() 
        { 
        }

        private class2(string p) 
        {   
        }
    }
}

老實說,這有點遲鈍,但它會強制執行最終的規則,以便class1class2唯一可以訪問class2(string p)構造函數的類型。 我認為你最好的選擇是考慮改變你的代碼設計。

你不能用普通的結構(使用訪問修飾符)來做到這一點,但你能做到的一種方法是使用反射:

public class Outer
{
    public Inner GetInstanceOfInner(string s)
    {
        var innerInstance = 
            typeof(Inner).GetConstructor(
                 System.Reflection.BindingFlags.NonPublic,  //Search for private/protected
                 null,   //Use the default binder
                 new[] { typeof(string) },  //Parameter types in the ctor
                 null)   //Default binder ignores this parameter
                 .Invoke(new[] { s }) as Inner; //Create and cast

        return innerInstance;
    }

    public class Inner
    {
        public Inner() { }
        private Inner(string s) { }
    }
}

使用反射,您可以使用BindingFlags.NonPublic調用私有或受保護的構造函數來查找適當的構造函數。 在那之后你。 .Invoke它以獲得對象的引用並將其轉換為強類型。

我會在這個例子中使用一個接口。 畢竟,界面正是您所描述的。

DotNetFiddle.net示例

using System;

public class Program
{
    // Properties you want others to have access too
    public interface ICredentialsValidator
    {
        bool IsTest(string userName);
    }

    public static void Main()
    {
        var b = new PublicClass().GetCredentialsValidator();

        Console.WriteLine(b.IsTest("test"));
        Console.WriteLine(b.IsTest("blah"));
    }

    public class PublicClass
    {
        public ICredentialsValidator GetCredentialsValidator()
        {
            return new PrivateClass();
        }

        private class PrivateClass : ICredentialsValidator
        {
            public bool IsTest (string userName)
            {
                return userName == "test";
            }
        }
    }
}

結果:

真正

您可以傳遞ICredentialsValidator ,但沒有人可以創建ICredentialsValidatorclass2 簡單的OOP。

雖然我發現這非常復雜且過於復雜。 我只想使用單例模式和Liskov替換原則的接口:

public interface ISecurity
{
  bool IsTest(string userName);
}

public sealed class Security : ISecurity
{
  private static readonly Lazy<Security> lazy =
    new Lazy<Security>(() => new Security());

  public static ISecurity Security Instance { get { return lazy.Value; } }

  private Singleton()
  {
  }

  public bool IsTest(string userName)
  {

  }
} 

然后任何人都會

Security.Instance.IsTest("test");

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM