循环 属性 c#

Looped property c#

    static TestInitialization()
    {
      client = new HttpClient();
      client.BaseAddress = new Uri( URL_BASE_ADRESS );
      client.DefaultRequestHeaders.Add( "auth-key", Auth_Token );
    }

    private const String path = @"f:\specialproject\authdata.txt";
    internal static readonly String Login = File.ReadLines( path ).First(); //login in this file must be the first line
    internal static readonly String Password = File.ReadLines( path ).Last();//password - as second line
    internal static String Auth_Token
    {
      get
      {
        if( Auth_Token != null )
          return Auth_Token;
        else
          return LoginAndGetToken();
      }
      set
      {
        Auth_Token = LoginAndGetToken();
      }
    }

    internal static String LoginAndGetToken()
    {
      HttpRequestMessage request = new HttpRequestMessage( HttpMethod.Post, $"{URL_BASE_ADRESS}/console/home/login" );
      request.Content = new StringContent( "{\"login\":\"" + TestInitialization.Login + "\",\"password\":\"" + TestInitialization.Password + "\"}", Encoding.UTF8, "application/json" );

      Auth_Token = client.SendAsync( request ).GetAwaiter().GetResult().Headers.GetValues( "auth-key" ).ToArray()[ 0 ];
      return Auth_Token;
    }

这是我的代码的一部分。当执行静态构造函数时,我尝试获取 Auth-Key 属性 - 在 getter 中,它在检查 null 时循环。

我该如何实现这个逻辑? (不添加额外的私有字段) 如果值为空,则执行 set 块。或具有 return 值的 LoginAndGetToken() 方法。

    internal static String Auth_Token
    {
      get
      {
        if( Auth_Token != null )
          return Auth_Token;
        else
          return LoginAndGetToken();
      }
      set
      {
        Auth_Token = LoginAndGetToken();
      }
    }

有两个堆栈溢出案例。 第一个在 get (return Auth_Token) 中,另一个在 set 中(LoginAndGetToken 方法设置 Auth_Token 值)

我想建议使用 Lazy<T> 和 factory like

internal static Lazy<String> Auth_Token = new Lazy<String>(LoginAndGetToken);

internal static String LoginAndGetToken()
{
  HttpRequestMessage request = new HttpRequestMessage( HttpMethod.Post, $"{URL_BASE_ADRESS}/console/home/login" );
  request.Content = new StringContent( "{\"login\":\"" + TestInitialization.Login + "\",\"password\":\"" + TestInitialization.Password + "\"}", Encoding.UTF8, "application/json" );

  return client.SendAsync( request ).GetAwaiter().GetResult().Headers.GetValues( "auth-key" ).ToArray()[ 0 ];
}

这可以像下面这样使用 Auth_Token.Value 来调用 :

client.DefaultRequestHeaders.Add( "auth-key", Auth_Token.Value );

PS没有附加字段条件看起来很奇怪(而且Auth_Token不是一个字段它是属性)

PPS是作业吗?方法数量有限制吗?你可以有一个 Auth_Token 属性 只是为了存储一个字符串值和方法 GetAuth_Token() 到 return Auth_Token 或者调用 LoginAndGetToken 如果没有Auth_Token

string GetAuth_Token()
{
  return Auth_Token = Auth_Token ?? LoginAndGetToken();
}

使用快捷方式属性实现时,例如:

public string MyProp { get; set; }

底层字段是隐式创建的。

但是当提供访问器的任何实现时,不会创建此隐式字段。如果 属性 需要保持任何状态,您必须自己定义所需的字段,例如:

public string MyProp
{
    get
    {
       if (myProp == null)
           myProp = SomeCodeToComputeMyProp();
       return myProp;
    }
    set
    {
        myProp = value;
    }
}
private string myProp = null;

补充说明:

  • setter 应该使用(隐式)value 参数并根据它设置 属性。虽然它做一些额外的检查和计算是完全有效的,但它不应该做完全不同的事情。忽略 value 并做一些与您完全不同的事情表明您的设计有问题。也许根本不应该有 setter ?或者只在您的 class?
  • 中使用一个私人的
  • 当 属性 访问器执行昂贵或阻塞的任务时,从您的 class 客户端角度来看,这会令人困惑且容易出错。 HTTP 请求应该在普通方法中执行,而不是在属性内部。

并且 是正确的:在这种情况下,您可能仍然需要 Lazy<T> 模式。

好的,谢谢大家的指教,我还是决定通过加个字段照样做。答案如下:

    private static String _auth_token;
    internal static String Auth_Token
    {
      get
      {
        if( _auth_token != null )
          return _auth_token;
        else
          return _auth_token = LoginAndGetToken();
      }
    }