是否可以在没有设置器的情况下在属性中设置值?

Posted

技术标签:

【中文标题】是否可以在没有设置器的情况下在属性中设置值?【英文标题】:Is is possible to set value in property without a setter? 【发布时间】:2019-06-16 16:01:31 【问题描述】:

我正在使用这个包 (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 类中只有一个空的构造函数 请添加更多详细代码!还要告诉你要在哪种情况下设置值。 答案是:从第 376 行开始阅读github.com/shawnmclean/Mandrill-dotnet/blob/master/src/Mandrill/…。该方法专为您的情况设计 谢谢,这正是我想要的。 【参考方案1】:

我想我找到了你所说的课程here。尽管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);

【讨论】:

【参考方案2】:

我知道您已经得到了针对您的特定情况的答案,但是由于问题是“是否可以在没有 setter 的情况下在属性中设置值?”并且明确地说您不能直接从类外设置值,我只是想提供一个这样做的例子......

如果您愿意使用反射,您实际上可以从类外部设置值。

你只需要有点棘手。

您需要滥用这样一个事实,即为 Auto 属性生成的私有字段是由编译器脱糖而不是由 JITer 生成的。

这意味着程序集中实际上会有一个这样命名的私有字段:k__BackingField.

编译器去糖添加 因为它们被开发人员代码添加为私有字段名称是非法的。

这是一个示例,我试图查找名为 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# 规范中指定的,并且它可能会在不同的编译器实现中发生变化。

【讨论】:

【参考方案3】:

很抱歉成为坏消息的承担者,但如果没有公共设置器,您无法直接从类外设置值。其他选项将通过构造函数或允许这样的方法。但您似乎没有任何可用的此类选项。

附带说明一下,只需检查该属性是否可能没有您可以作为一个整体设置的父属性。例如在 C# 中使用字体时,例如设置标签的字体。某些 Font 对象的属性是“只读的”,不能在外部设置。但是可以设置 Font 对象本身。因此,在这种情况下,您必须在本地创建一个新的 Font 对象并设置所需的道具,然后将其分配/设置为新的 Font。

希望您能及时找到解决办法。

更新:

Rufo 爵士刚刚给了你解决方案:

答案是:阅读时间 github.com/shawnmclean/Mandrill-dotnet/blob/master/src/Mandrill/… 从第 376 行开始。该方法专为您的情况设计

【讨论】:

你忘了说可能有一种方法可以完成这项工作(事实上,有一个);o) @SirRufo - 不,我确实提到过,只是添加了您的解决方案。赞一个!

以上是关于是否可以在没有设置器的情况下在属性中设置值?的主要内容,如果未能解决你的问题,请参考以下文章

Python属性在构造函数中设置值时不使用setter

在 CoreData 中设置值会使应用程序崩溃

从对象 php 的 jquery 数组中设置值?

iOS 在组件中存储随机属性,例如没有子类的 UITextField

我们可以在没有循环的情况下在 oracle 中获得列表属性的总和吗?

MySQL使用默认值与在查询中设置值是不是有任何性能差异?