How to check if the field in the class is serializable? - c#

I am working on my own implementation of JSON serializer and I need to get all serializable fields of the class.
For example, I have class like this:
[Serializable]
class TestClass
{
public int i;
public string s;
[NonSerialized]
public string ignore;
}
So I don't want to serialize ignore. In this code I try to print all serializable fields:
foreach (FieldInfo field in typeof(TestClass).GetFields())
{
if (field.FieldType.IsSerializable)
{
Console.WriteLine (field.Name);
}
}
Eventually ignore is printed as well as others. What am I doing wrong?

FieldType.IsSerializable checks if the type of the field is serializable, not the field itself. Instead, use IsNotSerialized off of the FieldInfo:
if (!field.IsNotSerialized)
{
Console.WriteLine(field.Name);
}
It's worth pointing out that the NonSerialized attribute gets special treatment by the compiler. Unlike most attributes, this ones does not actually get emitted into CIL, rather it is a flag on the field, so checking for the existence of the attribute may not work. Instead, it is appropriate to check the field's flag directly.

Related

What is the best practice for serializing C# immutable structs?

I usually make my structs read-only. However, serialization libraries (e.g. DataContractSerializer) expect the serialized fields or attributes to be read/write.
So my options I believe are:
Make my fields writable just to appease serializers
Create proxy objects for the purpose of serialization
Auto-generate proxies using reflection
Auto-generate serialization/deserialization functions by trying to guess an
appropriate constructor using heuristics or an attribute.
What do people normally do in this situation?
DataContractSerializer is able to serialize read-only fields if you initialize it like this
var serializer = new DataContractSerializer(
typeof(ToSerialize),
new DataContractSerializerSettings()
{
SerializeReadOnlyTypes = true
});
But this will only work one-way if you want to deserialize a class with a property that has only a getter. So you can serialize, but not deserialize something like this:
[DataContract]
public struct ToSerialize
{
public ToSerialize(string a)
{
PropertyToSerialize = "a";
}
[DataMember]
public string PropertyToSerialize { get; }
}
So either you add a private set to your property, or add a backing field and mark it with [DataMember] attribute.
[DataContract]
public struct ToSerialize
{
public ToSerialize(string a)
{
backingField = "a";
}
public string PropertyToSerialize => backingField;
[DataMember]
string backingField;
}
By using private setters you are making it hard to change the state of the object (you can probably do it using reflection). So if there are no methods changing the fields in your struct and all properties have private setters, your struct is technically immutable. I would go for a private setter in your case, it is more readable and takes less amount of effort than playing with reflection.

Passing Attributes of a Auto-Implemented Property to its field

I have the following Problem: I would like to add an attribute to an auto-implemented property prop of a class Foo in the first step.
In a second step I'm iterating over all fields of Foo and I copy values to these fields (values of fields of auto-implemented Properties are also found and copied). In this part I need access to the information of the Attribute.
class FieldSetter
{
// This Method is called from outside and should work for any class
private void SetFieldValues(object unknownObject)
{
foreach (var field in
unknownObject.GetType().GetFields(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance |
BindingFlags.Static).Where((field) => !field.IsLiteral))
{
if (!EvalAttribute(Attribute.GetCustomAttributes(field))) // the Attribute should be accessed here
{
// Do something if no special Information is set
field.SetValue(a, "default Value");
}
else
{
// Do special things
field.SetValue(a, "special Value");
}
}
}
internal static bool EvalAttribute(Attribute[] attributes)
{
foreach (System.Attribute attr in attributes)
{
var myAttr = attr as MyAttribute;
if (myAttr != null)
{
if (myAttr.SomeAttributeValues == "Specific Attribute Value")
{
return true;
}
}
}
return false;
}
}
// This class is a example for how a given Object can look like
class Foo
{
[MyAttribute("Example Information")] // This Attribute won't be accessed via prop-Field
int prop { get; set; }
[MyAttribute("Another Example Information")] // This Attribute won't be accessed via prop-Field
int field;
//... lots of other fields and properties
}
[System.AttributeUsage(System.AttributeTargets.All)]
class MyAttribute : Attribute
{
public MyAttribute(string someInformation)
{
SomeAttributeValues = someInformation;
}
public string SomeAttributeValues;
}
You can't do this. If you need to have the attribute on the field, you need to declare the field yourself and not use auto-properties. Alternately, you can reflect over the properties which will have the attribute when you look for them.
If you can guarantee that the properties you're interested in will always be auto-implemented, and you have some idea of what compiler will be used to compile the types you're interested in, you could leverage the fact that the backing fields for auto-generated properties follow a specific naming convention. For example, the code you've provided ends up with a field name like this:
<prop>k__BackingField
This is a distinctive name, which cannot be produced directly by C# code, so if you run into a field with a name like this you could parse out the property name from between the angle brackets, and use GetProperty() on that name.
However, this is a hacky solution because:
The name used for backing fields is an implementation detail, which could theoretically change in future versions of .NET, or for alternative compilers like Mono.
There's nothing to ensure that the fields you find will always be tied to auto-properties. What would your expectations be if you ran into this?
class Foo
{
int field;
[MyAttribute("Example Information")]
int prop { get{return field;} set {return field;} }
//... lots of other fields and properties
}
I'd strongly suggest that you spend more time analyzing what your real business need and constraints are, and see if there's not another, more robust way to approach this problem.

How to mark members that are required by runtime but shouldn't be used in code?

Sometimes the .NET runtime requires us to create public setters for properties which should really be read-only. For example:
XmlSerializer requires serialized properties to be writable, even if we only serialize one-way.
I have an unusual case in WPF where I need to have a TwoWay binding within a MultiBinding, even though conceptually the bound value will never change. This requires properties to be writable.
In each of these cases, I can leave the setter empty without affecting the functionality, but this is likely to lead to confusion down the line.
Given that I can't avoid having public setters on these properties, is there a way to generate compiler warnings when the setters are accessed? The attributes [Deprecated] and [Obsolete] would do the job, but the wording/intent isn't right.
The way I approach this problem is that I simply don't compromise the integrity my types for the purposes of serialization. The process of serialization is all about data and very little about behavior. I refuse to compromise the behavior of my types for a data only scenario.
Instead I design my types for the most efficient + safe usage. If the resulting type is not serializable and I find a scenario that requires it, I will create separate types which exist solely for the purpose of serializing my other types.
Here's a quick sample.
// My Core Immutable Type
namespace MyProject {
public sealed class Student {
private readonly string _name;
public string Name {
get { return _name; }
}
public Student(string name) {
_name = name;
}
}
}
// My Xml Serialization Type
namespace MyProject.Serialization {
public class SerializableStudent {
public string Name;
public SerializableStudent(Student source) {
Name = source.Name;
}
public Student ConvertToStudent() {
return new Student(Name);
}
}
}
For serialization, specifically, you can define the process manually by implementing the ISerializable interface.

how to serialize some attribute in some condition

When using XML serialization to serialize a class, how to make some attribute be outputted conditionally. i.e. In some case, it output this attribute, in other cases, it does not.
You can create an additional property which is called MyPropertySpecified, which returns a boolean.
When this property returns true, the MyProperty property will be serialized. When it returns false, it will not be serialized.
Also, you'd want to decorate that property with the XmlIgnoreAttribute, so that this specific property is not serialized.
Example:
public class Person
{
public string Name
{
get;
set;
}
[XmlIgnore]
public bool NameSpecified
{
get { return Name != "secret"; }
}
}
While works and is a rather short solution, the propertyNameSpecified pattern has some drawbacks in my opinion (pollutes the interface of your class; relies on property names; introduces implicit behavior).
If you only need to implement a simple condition (e.g. don't serialize a default value), then the DefaultValue attribute is a better choice.
For example:
public class PurchaseOrder
{
[DefaultValue("2002")]
public string Year;
}
If Year has the value "2002", it will be omitted from the XML output.
You can use OnSerializingAttribute while serializing which allows us to invoke method before serialization. You can get more information about it here
Imho you would need to implement IXmlSerializable on the class and implement the WriteXml and ReadXml methods in such a way that they only write the attribute based upon the conditions you specify and can handle reading with or without that particular attribute present upon deserialization.
IXmlSerializable at Msdn

Acessing the backing field in an auto property

Is there any way to access the backing field for a property in order to do validation, change tracking etc.?
Is something like the following possible? If not is there any plans to have it in .NET 4 / C# 4?
public string Name
{
get;
set
{
if (value != <Keyword>)
{
RaiseEvent();
}
<Keyword> = value;
}
}
The main issue I have is that using auto properties doesn't allow for the same flexibility in validation etc. that a property with a explicit backing field does. However an explicit backing field has the disadvantage in some situations of allowing the class it is contained in to access the backing field when it should be accessing and reusing the validation, change tracking etc. of the property just like any other class that may be accessing the property externally.
In the example above access to the backing field would be scoped to the property thus preventing circumvention of the property validation, change tracking etc.
Edit: I've changed < Backing Field > to < Keyword >. I would propose a new keyword similar to value. field would do nicely although I'm sure it's being used in a lot of existing code.
No there isn't. If you want to access the backing field, then don't use auto properties and roll your own.
I agree that it would be great to have a field that was only accessible by the property and not by the rest of the class. I would use that all the time.
As the MSDN states:
"In C# 3.0 and later, auto-implemented
properties make property-declaration
more concise when no additional logic
is required in the property accessors.
They also enable client code to create
objects When you declare a property as
shown in the following example, the
compiler creates a private, anonymous
backing field can only be accessed
through the property's get and set
accessors."
Since you have additional logic in you accessors, the use of auto-implemented properties is not appropriate in your scenario.
While the backing field does exist, it is given a mangled name to stop you referencing it easily - the idea is that you never reference the field directly. For interests sake, you can use Reflector to disassemble your code and discover the field name, but I would recommend you not use the field directly as this name may indeed be volatile, so your code could break at any time.
Having read your comments in Mehrdad's answer, I think I understand your problem a bit better.
It appears that you are concerned about the ability of the developer to access private state in the class they are writing, bypassing your validation logic, etc. This suggests that the state should not be contained in the class at all.
I would suggest the following strategy. Write a generic class that represents a ValidatedValue. This class holds only the backing value and only allows access/mutation via get and set methods. A delegate is passed to the ValidatedValue to represent the validation logic:
public class ValidatedValue< T >
{
private T m_val;
public ValidationFn m_validationFn;
public delegate bool ValidationFn( T fn );
public ValidatedValue( ValidationFn validationFn )
{
m_validationFn = validationFn;
}
public T get()
{
return m_val;
}
public void set(T v)
{
if (m_validationFn(v))
{
m_val = v;
}
}
}
You could, of course, add more delegates as required (eg, to support pre/post change notification).
Your class would now use the ValidatedValue in place of a backing store for your property.
The example below shows a class, MyClass, with an integer that is validated to be less than 100. Note that the logic to throw an exception is in MyClass, not the ValidatedValue. This allows you to do complex validation rules that depend on other state contained in MyClass. Lambda notation was used to construct the validation delegate - you could have bound to a member function instead.
public partial class MyClass
{
private ValidatedValue<int> m_foo;
public MyClass()
{
m_foo = new ValidatedValue<int>(
v =>
{
if (v >= 100) RaiseError();
return true;
}
);
}
private void RaiseError()
{
// Put your logic here....
throw new NotImplementedException();
}
public int Foo
{
get { return m_foo.get(); }
set { m_foo.set(value); }
}
}
Hope that helps - somewhat off the original topic, but I think it's more inline with your actual concerns. What we have done is taken the validation logic away from the property and put it on the data, which is exactly where you wanted it.
No, but you can in a subclass:
public class Base
{
public string Name
{
get;
virtual set;
}
}
public class Subclass : Base
{
// FIXME Unsure as to the exact syntax.
public string Name
{
override set
{
if (value != base.Name)
{
RaiseEvent();
}
base.Name = value;
}
}
}
If you're gonna do so, why you are using auto properties?!
A simple property has done it way back in 1.0. I don't think it makes sense to add complexity to the language for every special case. You either need the property to do plain store/retrieve model or need more than that. In the latter case, a normal property will do.
You can't do this I'm afraid. That's one of the reasons I started writing MoXAML Power Toys, to provide the ability to convert automatic properties into Notify properties.

Categories

Resources