簡體   English   中英

是否可以在沒有 setter 的情況下在屬性中設置值?

[英]Is is possible to set value in property without a setter?

我正在使用這個包( https://github.com/shawnmclean/Mandrill-dotnet )在 .net 應用程序中實現 mandrill 現在有一個模型“EmailMessage”用於發送電子郵件。 在 EmailMessage 模型內部有一個屬性“GlobalMergeVars”:

   [JsonProperty("global_merge_vars")]
   public List<MergeVar> GlobalMergeVars { get; }

現在我們可以看到 GlobalMergeVars 沒有設置器,但我必須為此設置一個值。 如果我們轉到此鏈接( https://mandrillapp.com/api/docs/messages.html )並單擊“嘗試”按鈕,那么我們可以為 GlobalMergeVars 設置值,但我認為我的包中存在一些問題使用。 但我不能切換到其他包,因為與其他包相比,它非常靈活。 那么無論如何要為 GlobalMergeVars 設置值?

PS:我也在github repo上打開了一個問題。 但是由於一些接近的最后期限,我需要快速修復。

我想我找到了你在這里談論的課。 盡管EmailMessage屬性與您在問題中顯示的屬性不同:

public class EmailMessage
{
    #region Public Properties
    ...
    /// <summary>
    ///   Gets the global_merge_vars.
    /// </summary>
    public List<MergeVar> GlobalMergeVars { get; private set; }

(這里的代碼與問題中給出的代碼之間的差異並不重要-我只是想知道我是否正在查看正確的文件!)

缺少的set等效於private set 該類中包含以下方法,該方法可讓您設置變量:

public void AddGlobalVariable(string name, dynamic content)
{
  if (GlobalMergeVars == null)
  {
    GlobalMergeVars = new List<MergeVar>();
  }

  var mv = new MergeVar {Name = name, Content = content};
  GlobalMergeVars.Add(mv);
}

我知道您已經為您的特定情況得到了答案,但是由於問題是“是否可以在沒有 setter 的情況下在屬性中設置值? ”並且非常明確地說您不能直接從類外部設置值,我只是想提供的只是做這樣的例子...

如果您願意使用反射,您實際上可以從類外部設置值。

你只需要有點棘手。

您需要濫用為 Auto 屬性創建的私有字段是由編譯器脫糖而不是由 JITer 創建的事實。

這意味着在程序集中實際上會有一個像這樣命名的私有字段:<[NameOfProperty]>k__BackingField。

Compiler desugaring 添加 < 和 > 因為它們被開發人員代碼添加為私有字段名稱是非法的。

這是一個示例,我試圖找到名為 GlobalIgnores 的屬性的私有支持字段,該屬性沒有設置器(意味着與擁有私有設置器相同)。

public class Configuration
{
    public Configuration()
    {
        GlobalIgnores = new List<string>{"IgnoredPropertyName"};
    }
    
    public IEnumerable<string> GlobalIgnores { get; }
}

protected IList<string> PropertyNamesToTempIgnore { get; } = new List<string>{"ReplacedIgnoredPropertyName"};

public void SetPrivateBackingFieldOfPropertyWithNoSetter()
{
    var configuration = new Configuration();
    var configurationType = configuration.GetType();
    const string globalIgnoresFieldName = "<GlobalIgnores>k__BackingField";
    var fieldInfo = configurationType.GetField(globalIgnoresFieldName, BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.DeclaredOnly);
    fieldInfo.SetValue(configuration, PropertyNamesToTempIgnore);
}

免責聲明:除非絕對必須,否則我不建議使用它,因為這些自動生成的私有字段的命名不是 100% 在 C# 規范中指定的,並且它可能會在不同的編譯器實現中發生變化。

不好意思,我很抱歉。但是,如果沒有公共設置者,您將不能直接從課堂之外設置值。 其他選項將通過構造函數或允許這樣做的方法。 但似乎您沒有任何可用的此類選項。

附帶說明一下,只要檢查該屬性是否沒有可以整體設置的父屬性即可。 例如在C#中使用字體時,例如設置標簽的字體。 Font對象的某些屬性是“只讀”的,不能在外部設置。 但是可以設置Font對象本身。 因此,在這種情況下,您必須在本地創建一個新的Font對象並設置所需的道具,然后將其分配/設置為新Font。

希望您能及時找到解決方法。

更新:

Rufo爵士剛剛給您提供了解決方案:

答案是:從376行開始,請閱讀github.com/shawnmclean/Mandrill-dotnet/blob/master/src/Mandrill/…。該方法是為您的情況設計的

暫無
暫無

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

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