C# 用户控件的struct属性的代码生成

C# 用户控件的struct属性的代码生成,c#,.net,winforms,struct,windows-forms-designer,C#,.net,Winforms,Struct,Windows Forms Designer,我创建了一个用户控件,如下所示: public partial class TestControl : UserControl { [DesignerSerializationVisibility(DesignerSerializationVisibility.Content)] public State MyState { get { return new State(this); } } internal int[] _interna

我创建了一个用户控件,如下所示:

public partial class TestControl : UserControl
{
    [DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
    public State MyState
    {
        get { return new State(this); }
    }

    internal int[] _internalStates;

    [TypeConverter(typeof(ExpandableObjectConverter))]
    public struct State
    {
        private TestControl _myControl;
        public State(TestControl _) { _myControl = _; }
        public int Data
        {
            get { return _myControl._internalStates[0]; }
            set { _myControl._internalStates[0] = value; }
        }
    }
}
然后我可以从工具箱中拖动控件,并在设计器中修改
数据

问题是设计器将在
InitializeComponent
方法中生成此代码:

this.testControl1.MyState.Data = 0;
但这一行将抛出一个错误:

无法修改“TestControl.MyState”的返回值,因为它不是变量

我理解为什么语句是错误的,问题是如何控制代码生成来纠正错误,例如生成这样的代码

var myState = this.testControl1.MyState;
myState.Data = 0;

更多信息

  • State
    struct只是在
    TestControl

  • 因此,我希望将
    状态
    保留为一个结构,以避免GC开销

  • TestControl
    类中不定义属性的原因是类中有多个状态,并且一个状态将包含多个属性,因此我需要包装修改方法,而不是在
    TestControl
    类中定义许多属性


  • 为什么
    Control.StructProperty.Member=Value出现编译时错误

    考虑以下陈述

    this.Control.StructProperty.Value = 0;
    
    StructProperty
    是一个属性,因此首先将执行它的getter,因为它是一个结构并且是一个值类型,所以它将返回一个结构的副本,并且为该副本设置一个属性是无效的。对情况了如指掌,它不会编译混乱的非工作代码,而是生成:

    无法修改“expression”的返回值,因为它不是 变数

    如何为结构属性生成工作代码?

    您可能已经注意到,由于相同的原因,无法分配
    this.Size.Width=100
    。表单为
    Size
    属性生成代码的方式是:

    this.Size = new Size(100,100);
    
    您还可以以相同的方式为属性生成代码,方法是通过从
    TypeConverter
    派生并在其
    ConvertTo
    方法中返回一个来实现类型描述符,从而使用您应该具有的用于结构的参数化构造函数为结构属性生成代码


    一般来说,我建议使用类而不是结构来处理这样的属性。

    你不能。问题不在设计师身上<代码>状态
    是一个结构。结构是一种值类型。您的属性
    MyState
    只有一个getter,它是只读的。因此,不能修改属性MyState的值(该值是struct)。上一个代码示例不会修改testControl1.MyState.Data的值,因为结构不是引用类型。(
    myState
    变量的值将仅是
    this.testControl1.myState
    属性值的一个副本,因此与它完全独立和不同)
    var myState=this.testControl1.myState;myState.Data=0
    将编译,但仍然是错误的,它不会更改
    MyState
    属性。至少对于这个语句,问题是显而易见的,例如
    var i=0;var j=i;j=1它会改变吗?虽然我建议对此类属性使用类,但如果您想正确生成struct属性的代码,您需要一个
    InstanceDescription
    ,正如我在回答中所述。@elgonzo感谢您的解释,但我理解错误,代码是自动生成的,因此,我只想找到一种方法,让设计师为属性分配生成正确的代码。是的,语句“
    this.Size.Width=100
    ”无效,因此通常
    Width
    属性不会显示在属性面板中,只有
    Size
    属性。正如你看到的我的代码,
    State
    的构造函数需要一个
    TestControl
    的实例,我无法想象如何获得该实例。例如,我在回答中描述的类型描述符的示例,请看,它有一个很好的示例。所有类型,如
    Point
    Size
    都有这样的类型描述符。宽度属性的故事是不同的<代码>大小
    属性将显示,您可以对其进行编辑。不管怎么说,我相信答案是很好地描述情况,你有你需要的所有信息。仔细阅读答案的第一部分,了解为什么
    this.Control.StructProperty.Value=0无效,请理解编译器错误的原因。然后阅读答案的第二部分以了解解决方案。我理解第一部分,这就是为什么我需要控制生成,并且我已经阅读了代码,因为
    大小
    结构包含宽度和高度成员,因此很容易构造
    InstanceDescriptor
    ,但是我的
    状态
    结构没有可使用的字段。您需要重新设计该结构,因为指向该结构外部的数组并具有控件引用的结构不是一个好的结构。但是,最快的修复方法是使用类。