Properties won't get serialized into the .designer.cs file - c#

In VS2010, control properties won't get serialized despite the ShouldSerializeFoo method, with the DesignerSerializationVisibility.Visible/Content as well.
Here's the code:
class Class1 : UserControl {
[Browsable(true)]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
public string Foo {
get; set;
}
public bool ShouldSerializeFoo() {
return true;
}
public Class1() {
Foo = "dupa";
}
}
However, the designer doesn't generate anything for this property:
//
// class11
//
this.class11.Location = new System.Drawing.Point(224, 262);
this.class11.Name = "class11";
this.class11.Size = new System.Drawing.Size(150, 150);
this.class11.TabIndex = 2;
this.class11.Load += new System.EventHandler(this.class11_Load);

You're mixing serialization schemes. The designer serialization (which is what DesignerSerializationVisibility is for) has nothing to do with the instance serialization mechanism (which is what ShouldSerializeXXX functions, among many other things, deal with).
DesignerSerializationVisibility.Content doesn't make much sense for a string (or any other immutable type). The designer can view a property's serialization as three types:
None - it never serializes anything about the property
Visible - it will serialize the actual value of the property
Content - it will serialize the property values of the value of the property.
By default, a property is considered Visible. I realize that my definition of Content might be a little confusing. What I mean by that is like this:
public class MyControl : Control
{
public class SomeOptions
{
public string Option1 { get; set; }
public string Option2 { get; set; }
}
[DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
public SomeOptions Options { get; private set; }
public string Foo { get; set; }
}
Now, when this class is serialized by the designer, it will look something like this:
// myControl1
this.myControl1.Foo = "value";
this.myControl1.Options.Option1 = "option1";
this.myControl1.Options.Option2 = "option2";
This should hopefully make more sense; marking a property as Content signifies that, rather than serializing the actual value of the property (in this case, it would be an instance of SomeOptions), it should serialize the property values of that value instead.
So, back to your question, that's why you don't want Content for a string property. Because strings are immutable, there's nothing for the designer to serialize. Either mark it as Visible or leave the attribute off entirely (since that's the default).
While it's possible to provide custom direction to the designer as to whether or not you want to serialize a particular property, it's a pretty involved (and nasty) process. The easy way, though, is to use the DefaultValue attribute on the property. If whether or not the property should be serialized can be determined by comparing its value to a constant (in other words, it's not dependent upon anything else at runtime, like the value of another property), you can decorate the property like this:
[DefaultValue("foo")]
public string Foo { get; set; }
If the designer then sees that the value of Foo is equal to "foo", then it won't serialize the property at all.

Related

C# Serialize WinForm

I am trying to serialize a winform, with the end goal of being able to recreate the values in the various controls of the form. My form contains the typical controls, buttons/radio buttons/checkboxes/textboxes/listbox/tab control.
I am receiving this error:
An exception of type 'System.InvalidOperationException' occurred
in System.Xml.dll but was not handled in user code
Additional information: There was an error reflecting type
'Receptionist_Program.Objects.Client.Client_NCQ'.
I setup properties for each value I want to save:
public bool CbMedTreat
{
get { return cbMedTreat.Checked; }
set { cbMedTreat.Checked = value; }
}
public List<Client_AddDoctor> TxtDocExplain // Client_AddDoctor is another form
{
get { return listDoctors; }
set { listDoctors = value; }
}
// etc, variety of string and bool properties
At the top of the class I have the decoration:
[Serializable]
public partial class Client_NCQ : Form
Finally, here is my code doing the serialization:
Client_NCQ badname = new Client_NCQ();
badname.Initialize();
badname.ShowDialog();
string result = "";
XmlSerializer xmlSerializer = new XmlSerializer(typeof(Client_NCQ));
// Error occurs here on above line: new XmlSerializer(typeof(Client_NCQ))
using (StringWriter textWriter = new StringWriter())
{
xmlSerializer.Serialize(textWriter, badname);
result = textWriter.ToString();
}
I tried two different things so far, first, I added the decoration [XmlIgnore] to the List<> property, this made no difference. Second, I tried ensuring that the constructor was empty and had no parameters.
Serializing an entire Form is a bad idea because it is not meant to be serialized:
it has a lot of properties that should not be serialized (e.g. displaying related properties)
even if it works properly, you will have a lot of data that is not relevant for your application's state
The correct solution is to keep all state information in your custom objects and bind to those objects using WinForm's databinding capabilities. If this means great changes to your application, try to serialize only the data that is relevant to constructing the state.
How can you know which data is relevant for application state?
Before constructing and showing the form, I expect that you are loading the data from a database, file etc. All that information should be contained in clearly defined objects of types marked with [Serializable] attribute. This way, it is easy to serialize and deserialize it at will.
Also, it is important to take into consideration version tolerant serialization or what happens when the form / state information is changed (e.g. a field is added) and an older XML is used to restore state.
Every form has its own mechanism to store and retrieve (serialize and deserialize) data and it does this automatically. However, the following conditions are to be met in order to use this feature automatically.
- All properties which are desired to be serialized must have public get and set accesor.
- If a certain property represents custom object such as user defined class or struct, the object must be adorned with [Serializable] attribute.
- Property which is desired to be serialized must not have [DesignerSerializationVisibility] attribute set to Hidden. By default it is Visible so not specifying this attribute at all is sufficiently serves the purpose.
Consider this example:
namespace MnM.Drawing
{
[Serializable, TypeConverter(typeof(ExpandableObjectConverter))]
public class Coordinates
{
public int X { get; set; }
[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
public int Y { get; set; }
public int Z { get; protected set; }
}
public class MyForm : Form
{
[Browsable(true), EditorBrowsable(EditorBrowsableState.Always)]
public Coordinates MyCoordinates { get; set; }
}
}
Now, MyForm will automatically serialize MyCoordinates object but...
Only property X will get serialized because it fits the requisite
status to qualify for auto serialization.
Property Y can not be serialized because of DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)
Property Z can not get serialized automatically because it does
not have public set accesor.
In order to serialize Y and Z, custom serialization code is required. In most cases, need of custom serialization does not arise and custom serialization can be done in many ways but its a vast topic.

How to let an Attribute in property 'A' know the existence of property 'B'?

How to let an Attribute in one property know the existence of another property?
Lets say i have this class, and like this, many others:
public class MyClass
{
[CheckDirty] //a custom attribute (that it is empty for now)
public int A { get; set; }
public int B { get; set; }
public string Description { get; set; }
public string Info { get; set; }
}
Somewhere in our program, if we want to see if an object changed values on any CheckDirty property, for example lets say it is diferent from DB, MyPropertyUtils.GetPropertiesIfDirty() does this, giving us an array of changed propertys, on any property with that attribute:
PropertyInfo[] MyPropertyUtils.GetPropertiesIfDirty(SomeBaseObject ObjectFromDB, SomeBaseObject NewValues);
Perfect.
So, lets say A changed and in this case Info holds some information we need(in another class might be any other property). If we want 'A' we just do property.GetValue(NewValues, null);
But we dont want 'A's value, we want 'A' or CheckDirty to tell us where to read some data we want. How can i tell my attribute CheckDirty where to get the values from?
I was thinking in giving an expression to CheckDirty but an Attribute's argument "must be a constant expression, typeof expression or array creation expression of an attribute parameter type"(thats what VS says).
So I decided, "ok, lets give it a string with the property's name", and so my try failed:
(this is all the code we need to work on, the rest was just to give some kind of context example)
public class CheckDirty : Attribute
{
public String targetPropertyName;
public CheckDirty(String targetPropertyName)
{
this.targetPropertyName = targetPropertyName;
}
}
public class MyClass
{
//Code fails on this line
[CheckDirty(BoundPropertyNames.Info)]
public int Id { get; set; }
public string Info { get; set; }
public static class BoundPropertyNames
{
public static readonly string Info = ((MemberExpression)
((Expression<Func<MyClass, string>>)
(m => m.Info)
).Body
).Member.Name;
}
}
This is the error i get:
An attribute argument must be a constant expression, typeof expression or array creation expression of an attribute parameter type
We do NOT want to pass the name of the proprety as a String saing [CheckDirty("Info")] because that way if anyone in the future changes the class, and in concrete the property's name, no error would get thrown in compile time by it, only occuring the error in run time, when an "edit" to that field would occur. Or maybe it would just not do anything because it could not find the property.
Any idea how to not use the strongly typed string as a property name?
You may use something like this, first declare an interface that will be implemented by every class that need dirty checking:
interface IDirtyCheckPropertiesProvider {
string GetPropertyName(string dirtyProperty);
}
then implement it like that
class DataEntity : IDirtyCheckPropertiesProvider {
[CheckDirty]
public int Id { get; set; }
public string Info { get; set; }
string GetPropertyName(string dirtyProperty) {
if (GetPropertyNameFromExpression(x => Id) == dirtyProperty)
return GetPropertyNameFromExpression(x => Info);
return null;
}
}
In class that will be responsible for handling dirty checks you must use this interface to get target property names.
There is a bit too much boilerplate that may be removed further by using Reflection API.
On the other hand using string for property names looks like more simple solution. If you use tool like Resharper - using string is a viable option - Resharper will automatically refactor string when you change property name.
Also for a long time string'ed property names were used in implementation of WPF INotifyPropertyChanged.
As comments suggested nameof is the best option in VS2015.

what the best way to declare a property

I'm switching from Objective-C to C# to start using the Unity engine. So I'm trying to soak in all the C# differences. Obj-C has the #synthesize that auto creates the getters and setters. To to be honest they're sort of new to me. In Obj-C I'd often do:
#synthesize myProperty = _myProperty;
Then use the _myProperty in the local class code and access that property outside of this class using myProperty. Or more accurately classInstance.myProperty.
Also in Obj-C you can declare a property to be readonly and not worry about accidentally changing it's value outside the class.
In C# I'm trying to write proper object oriented code and I struggle with this. I'm a C coder at heart and am comfortable having access to everything everywhere, which I know is bad and unnecessary. I also don't want to expose tons of properties to the GameObject Inspector. I prefer to do as much programmatically as possible.
So what is the best way to declare properties so I can access them from another class but also so they are not exposed in the Inspector? Here are some possibilities that I've encountered and used:
// 1. public static - public without being exposed in inspector
public static int myProperty;
// 2. the public _text doesn't appear in the inspector but the text one does.
public string _text;
public string text {
get { return _text; }
set {
_text = value;
}
}
// 3. private _underscore version with no setter - does removing the set make it read only?
private float _current;
public float current {
get { return _current; }
}
// 4. creating my own getter function
private int myValue;
...
int GetMyValue() {
return myValue;
}
Also.. I read somewhere that in .NET you shouldn't use underscores in property names. I don't really know what the underscore version of the property does or represents. I thought in Obj-C it effected the scope, but don't really know.
Am I even correct in calling variables properties?
Someone suggested prop tab tab which produces this:
public object MyProperty {
get;
set;
}
Unfortunately that doesn't really answer my question about read only. Is an int or string even an object? It's not in Obj-C.
Public variables (not fields) are shown in the Unity inspector. If you want a public variable to be hidden, you can preface it with NonSerialized, like this:
[System.NonSerialized]
public bool m_HideWhenInactive = false;
You can also avoid this problem entirely by making it a property. No properties are shown in the inspector:
public bool m_HideWhenInactive { get; set; }
As a fun bonus (not your question, I know), you can have a property that's world-read, private-write:
public bool m_HideWhenInactive { get; private set; }
And finally, if you DO want a variable to be serialized and stored in a prefab, but you don't want the designers editing it (if you intend to write a custom editor class), there's a different annotation for that:
[HideInInspector]
public bool m_HideWhenInactive = false;
Static fields are never shown in the inspector.
The NonSerialized and HideInspector attributes are the two options you must consider to hide members of the class from the Unity inspector. NonSerialized is not specific to Unity, HideInspector is specific to Unity. Unity looks for both of these attribute in your compiled code to determine what gets exposed in the inspector.
If you want a publicly read only property you declare it like so...
[System.NonSerialized]
private string _text;
/// <summary>
/// Gets the Text
/// </summary>
/// <remarks>May be set within this class or derived classes</remarks>
public string Text {
get { return _text; }
protected set {
_text = value;
}
}
You seem to be having issues with the meaning of access modifiers...
See this page...
https://msdn.microsoft.com/en-us/library/wxh6fsc7.aspx
Briefly...
public = accessible from anywhere, do not declare backing variables on properties as public, otherwise people can simply skip your property accessor.
protected = accessible within your class and from classes inheriting the class
internal = accessible within the same assembly
protected internal = accessible within the same assembly and from
classes inheriting the class
private = accessible only within your class
You can do away with backing variables simply by declaring
/// <summary>
/// Gets or sets the Text
/// </summary>
public string Text { get; set; }
/// <summary>
/// Gets the current
/// </summary>
public float Current { get; protected set; }
Since the advent of auto-implemented variables, there are no technical reasons for creating properties with backing variables unless you have additional logic you would like executed on the get and/or set.
e.g you wanted to create Observable entities that raise an event when a property is changed...
private int _id;
public int ID
{
get
{
return _id;
}
set
{
if (_id != value)
{
OnIDChanging(value);
ReportPropertyChanging("ID");
_id = StructuralObject.SetValidValue(value);
ReportPropertyChanged("ID");
OnIDChanged();
}
}
}
In terms of coding standards, there are plenty of them on the net. I'd recommend IDesign's...
http://www.idesign.net/downloads/getdownload/1985
You'll notice I changed the casing on the code you posted, the casing I've used adhere's to IDesign's naming guidelines
The correct way to create properties really depends on what it is you're trying to accomplish. If you're only wanting to have a property be created for further use you can create the shorthand way:
public object MyProperty { get; set; }
If more functionality is required, you can add additional functionality, such as:
private int _myInt;
public int MyInt {
get { return this._name; }
set {
if (this._name == 1) {
this._name = value;
} else {
this._name = 0;
}
}
}
The answer of your question is it simply depends on what it is you're looking to achieve and both ways are accepted.
The use of getter and setter methods, such as those found in Java, are frowned upon in C#.
To answer your other question, String is an object in C#. int is a primitive type.
Here's a quick summary of your problems.
There is a so called snippet in C# that allows you to quickly generate code. The quick shortcut for it is typing prop and then pressing tab which would generate a code to something like this.
public int MyProperty { get; set; }
Now if you're going to create fields, and you dont want to expose that to an instance. You should make it private.
Example
private int myVar; // private is not exposed on instances only public properties are
public int MyProperty
{
get { return myVar; }
set { myVar = value; }
}
Now for static fields, static fields/properties are type accessible. So to hide them, you only have to make them private
Example
private static bool myProp; // can't be accessed on the Program Type
public static bool MyProp { get; set; } // can be accessed on the Program Type
class MyClass
{
public MyClass()
{
Program.MyProp = true;
Program.myProp= true; // wont build
}
}
If you want it to be readonly and prevent modification, you can do it like this.
public int MyProperty { get; private set; } // can get but not set
private int myVar;
public int MyProperty
{
get { return myVar; } // same as the top but with a field
}
For a deeper and better understanding, please do read about What are Access Modifiers in C#?
Property patterns in the context of the Unity engine tend to differ slightly to the 'norm' of C# because of you are often interested in making them tweakable data in the editor. This means serialization.
Unity cannot serialize properties
Unity can serialize fields of primitive types and types inheriting from UnityEngine.Object are serialized references
Unity can serialize list and arrays of the types mentioned above as well
Serialized fields on MonoBehaviours are exposed in the editor and are editable
public fields are serialized by default and private fields if they are marked with the [SerializeField] attribute.
Unity also serializes fields on classes marked with [System.Serializable] if the class is a field on a MonoBehavior
For a more in-depth discussion see: https://blogs.unity3d.com/2014/06/24/serialization-in-unity/
The following pattern is common, the backing field can be set by the developer, without needing to recompile, and cannot be changed by external code at run-time.
[SerializeField]
private int editableInEditor;
public int NotEditableInEditor
{
get { return editableInEditor; }
}
So is this pattern, a lazy-getter.
private DerivedMonoBehaviour component;
public DerivedMonoBehaviour Component
{
get
{
if(component == null)
{
// Note: Using the null-coalescing operator ??
// is inadvisable when dealing with UnityEngine.Object
// references.
// See: https://blogs.unity3d.com/2014/05/16/custom-operator-should-we-keep-it/
component = GetComponent<DerivedMonoBehaviour>();
}
return component;
}
}

How to make a property required in c#?

I have requirement in a custom class where I want to make one of my properties required.
How can I make the following property required?
public string DocumentType
{
get
{
return _documentType;
}
set
{
_documentType = value;
}
}
If you mean "the user must specify a value", then force it via the constructor:
public YourType(string documentType) {
DocumentType = documentType; // TODO validation; can it be null? blank?
}
public string DocumentType {get;private set;}
Now you can't create an instance without specifying the document type, and it can't be removed after that time. You could also allow the set but validate:
public YourType(string documentType) {
DocumentType = documentType;
}
private string documentType;
public string DocumentType {
get { return documentType; }
set {
// TODO: validate
documentType = value;
}
}
.NET 7 or newer
Syntax
public class MyClass
{
public required string Name { get; init; }
}
new MyClass(); // illegal
new MyClass { Name = "Me" }; // works fine
Remarks
The required properties must declare a setter (either init or set).
Access modifiers on properties or setters cannot be less visible than their containing type, as they would make impossible to initialize the class in some cases.
public class MyClass
{
internal required string Name { get; set; } // illegal
}
Documentation
Official documentation here
Feature demo here
.NET 6 or older
See this answer
If you mean you want it always to have been given a value by the client code, then your best bet is to require it as a parameter in the constructor:
class SomeClass
{
private string _documentType;
public string DocumentType
{
get
{
return _documentType;
}
set
{
_documentType = value;
}
}
public SomeClass(string documentType)
{
DocumentType = documentType;
}
}
You can do your validation – if you need it – either in the property's set accessor body or in the constructor.
With the release of .NET 7 and C# 11 in November 2022 you can now use the required modifier this way:
public class Person
{
public Person() { }
[SetsRequiredMembers]
public Person(string firstName) => FirstName = firstName;
public required string FirstName { get; init; }
public int Age { get; set; }
}
And when you don't have the required properties it will throw an error when you try to initialize an object.
For more information refer to:
https://learn.microsoft.com/en-us/dotnet/csharp/whats-new/csharp-11#required-members
https://learn.microsoft.com/en-us/dotnet/csharp/properties#init-only
Add a required attribute to the property
Required(ErrorMessage = "DocumentTypeis required.")]
public string DocumentType
{
get
{
return _documentType;
}
set
{
_documentType = value;
}
}
For custom attribute detail Click Here
I used an other solution, not exactly what you want, but worked for me fine because I declare the object first and based on specific situation I have different values. I didnt want to use the constructor because I then had to use dummy data.
My solution was to create Private Sets on the class (public get) and you can only set the values on the object by methods. For example:
public void SetObject(string mandatory, string mandatory2, string optional = "", string optional2 = "")
This one liner works in C# 9:
public record Document(string DocumentType);
new Document(); // compiler error
new Document("csv"); // correct way to construct with required parameter
This explains how it works. In the above code, Document is the name of the class or "record". That first line of code actually defines an entire class. In addition to this solution essentially making a required DocumentType property (required by an auto implemented constructor), because it uses records, there are additional implications. So this may not always be an appropriate solution, and the C# 11 required keyword will still come in handy at times. Just using record types doesn't automatically make properties required. The above code is a special syntax way of using records that essentially has this effect as well as making the property init only and causes a deconstructor to be automatically implemented.
A better example would be using an int property instead of a string since a string could still be empty. Unfortunately I don't know of any good way to do extra validation within the record to make sure the string is not empty or an int is in range, etc. You would have to go deeper down the TOP (type driven development) rabbit hole, which may not be a bad thing. You could create your own type that doesn't allow empty strings or integers outside your accepted range. Unfortunately such an approach would lead to runtime discovery of invalid input instead of compile time. There might be a better way using static analysis and metadata, but I've been away from C# for too long to know anything about that.

can we access properties from constructor

I am working on a CSharp code where in constructor i need to access properties of that class. Logically it looks troublesome to me since i will be accessing properties of the object that hasn't is still under construction.
Its an old code using c# version 4.0 and i am kind of refactoring it so that's why can't redesign everything from scratch.
Thanks
class employee
{
employee()
{
int square = count * count;
}
private int count {get;set;}
}
There is nothing wrong with that, except that count will always be 0.
There is (almost) no such thing as a "partially-constructed" object in .Net, except for an object that hasn't set all of its state in the constructor.
If you're constructing the class, and none of the properties have been set previously in the constructor and none of the properties are static and set elsewhere, the values will be default or null, so there's no point getting what they contain. Otherwise, the constructor is the perfect place to set your properties to something.
At construction time you may set a property, but unless it has a static member backing the getting or is a value type, you will get a null value until you set it.
public class WhatClass
{
public WhatClass()
{
int theCount = Count; // This will set theCount to 0 because int is a value type
AProperty = new SomeOtherClass; // This is fine because the setter is totally usable
SomeOtherClass thisProperty = AProperty; // This is completely acceptable because you just gave AProperty a value;
thisProperty = AnotherProperty; // Sets thisProperty to null because you didn't first set the "AnotherProperty" to have a value
}
public int Count { get; set; }
public SomeOtherClass AProperty { get; set; }
public SomeOtherClass AnotherProperty { get; set; }
}
Yes, C# allow this, but sometime better to have private field which is wrapped by public property and in class method work only with field. In your case I would recommend to remove private property and use class field variable instead. If consumers of your class potentially may want to access a property - make it public with a private setter, this kind of autmatic property is an other alternative for privatr field wrapped by a property.

Categories

Resources