I'm trying to deserialize a piece of XML that specifies a .NET type to an instance of System.Type. Given
<SomeObject>
<SomeType>System.String, mscorlib</SomeType>
</SomeObject>
To deserialize to a class;
public class SomeObject
{
public Type SomeType { get; set; }
}
Annoyingly, I've actually done this before a while back but without access to that source code and not being able to remember, this has proven very difficult to research the solution given the keywords needed ("Xml", "Deserialize", "Type" gives pretty much everything under the sun).
From what I remember, there is a simple Attribute that I put on the SomeType property and the XmlSerializer takes care of it from there. Does anyone know what attribute I need or am I mis-remembering?
If you don't want to have additional property of type string (usual solution to this problem) - you can use proxy class like this:
public class XmlTypeProxy : IXmlSerializable {
private string _typeName;
public XmlTypeProxy() {
}
public XmlTypeProxy(string typeName) {
_typeName = typeName;
}
public XmlSchema GetSchema() {
return null;
}
public void ReadXml(XmlReader reader) {
_typeName = reader.ReadString();
}
public void WriteXml(XmlWriter writer) {
writer.WriteString(_typeName);
}
public static implicit operator Type(XmlTypeProxy self) {
return Type.GetType(self._typeName);
}
public static implicit operator XmlTypeProxy(Type self) {
return new XmlTypeProxy(self.AssemblyQualifiedName);
}
}
What this class does is just stores type assembly qualified name as string and defines implicit conversion operator from and to Type type. Then you just need to decorate SomeType with XmlElement attribute and specify it's Type is XmlTypeProxy:
public class SomeObject {
[XmlElement(Type = typeof(XmlTypeProxy))]
public Type SomeType { get; set; }
}
Now, because there is implicit converstion from Type to XmlTypeProxy (and visa versa) - both serialization and deserialization will work as you expect.
While I've marked Evk's answer as correct (and it is if you are deserializing more than one Type property), I actually went with a simpler approach in the end.
Based on this answer, I modified by SomeObject to;
public class SomeObject
{
public string SomeTypeName
{
get { return SomeType.AssemblyQualifiedName; }
set
{
var converter = new TypeNameConverter();
SomeType = (Type)converter.ConvertFrom(value);
}
}
[XmlIgnore]
public Type SomeType { get; set; }
}
While a shorter piece of code for a single property, it's not as robust as the accepted answer. I'm recording here has the two approaches may help others.
Related
So, what I want is to serialise and deserialise some JSON using a generic field wrapper class.
I do not want to write some custom JsonConverter class.
I do wish to keep it simple and write some implicit operator type conversion. The following minimal piece of C# code is where I am at now .... just enough to demonstrate the issue and no more. Don't overlook the implicit operators.
using Newtonsoft.Json;
using System;
namespace test
{
public struct SofT<T>
{
[JsonProperty]
public T TValue { get; set; }
public static implicit operator SofT<T>(string jtoken)
{
return new SofT<T>()
{
TValue = (T)Convert.ChangeType(jtoken, typeof(T))
};
}
public static implicit operator string(SofT<T> soft)
{
return soft.TValue?.ToString() ?? "";
}
}
[JsonObject(MemberSerialization.OptIn)]
public class Something
{
[JsonProperty]
public SofT<int> TestStructInt { get; set; }
[JsonProperty]
public SofT<decimal> TestStructDecimal { get; set; }
}
public class Program
{
public void Run()
{
var json = "{ \"TestStructInt\" : \"12\", \"TestStructDecimal\" : \"3.45\"}";
var modelDeserialised = JsonConvert.DeserializeObject<Something>(json);
var modelReserialised = JsonConvert.SerializeObject(modelDeserialised);
Console.WriteLine(modelReserialised);
}
static void Main(string[] args)
{
new Program().Run();
}
}
}
The JSON string is deserialised perfectly.
The model object is not reserialised correctly.
The string that is spat out to the console is:
quote {"TestStructInt":{"TValue":12},"TestStructDecimal":{"TValue":3.45}}
The string I expect, or better put want, to be spat out to the console is the same structure in the source JSON, ie:
quote {"TestStructInt":"12"},"TestStructDecimal":"3.45"}}
I am asking for a second pair of eyes to point out my error (and yes I can see the error, the annotation of Value with [JsonProperty], but it seems necessary for default serialisation).
This question already has answers here:
Generic list of generic objects
(3 answers)
Closed 4 years ago.
I have an object that I want to put into a List or Collection. Is there a way to do that without having the T specified?
I want to do something like this: List<CommonProperty<T>>
Here's the object for reference:
internal class CommonProperty<T>
{
public string Name { get; set; }
public PropType Type { get; set; }
public List<T> PossibleValues { get; set; }
private T _value;
public T Value
{
get { return _value; }
set
{
if (!_value.Equals(value))
{
_value = value;
}
}
}
}
No, you can't use open generic types like that.
You could have a List<CommonProperty<T>> within a context where T is already a type parameter:
public class Foo<T>
{
static void Bar()
{
// This is fine, but is not what you're looking for - it uses
// the type parameter T as the type argument
List<CommonProperty<T>> list = new List<CommonProperty<T>>();
}
}
Typically the solution here is to have a non-generic base class or interface which the generic class or interface derives from:
// Consider making it abstract
internal class CommonProperty
{
public string Name { get; set; }
public PropType Type { get; set; }
}
internal class CommonProperty<T> : CommonProperty
{
public List<T> PossibleValues { get; set; }
private T _value;
public T Value
{
get => _value;
set
{
// TODO: Is this really necessary?
if (!_value.Equals(value))
{
_value = value;
}
}
}
}
You can then create a List<CommonProperty>... although be aware that it's entirely possible that you could end up with an element which wasn't a CommonProperty<T> at all that way.
From the List<CommonProperty> you'd be able to retrieve the names and types of all the properties - but the values wouldn't be available without casting to the specific type. You could have an abstract object Value { get; set; } property in the base class, which was then overridden in the derived class, potentially - but it's not clear whether that's necessary or helpful in your use case.
I think the closest you can get is to define an interface to match an un-typed (specific) CommonProperty, using Object instead of the T. Then have your CommonProperty<T> implement that interface. Now you can use the interface with your list.
But this isn't great. You'll lose a lot of nice type checking, and have to do more casting. If this is the primary way you'll use these objects, there's not much point to having a generic class at all anymore.
It is not possible to put a mixture of generics instantiated with different type arguments into the same collection. Such collection would not be useful anyway, because the caller would be expected to supply T for each item at compile time.
Suppose you could do what you want, i.e.
// imagine that you could do this
List<CommonProperty<T>> mixedList = GetAllProperties();
You would be forced to supply T once you start using items from that list, i.e.
foreach (CommonProperty<T> prop in mixedList) {
... // ^^^
... // Here you would need to specify T, but you don't know which one
}
In other words, such list would be unusable.
A list of properties of a specific type, on the other hand, would be useful:
List<CommonProperty<string>> stringPropList = GetPropertiesOfType<string>();
foreach (CommonProperty<string> prop in stringPropList ) {
...
}
Therefore, one solution to your problem would be building GetPropertiesOfType<T> method returning List<CommonProperty<T>> bound to type T from the caller.
An alternative approach would be to make CommonProperty non-generic, and let the caller check the type at runtime:
internal class CommonProperty {
public string Name { get; set; }
public PropType Type { get; set; }
public List<T> GetPossibleValues<T> { get; set; }
private object _value;
public T GetValue<T>() {
return (T)_value;
}
public void SetValue<T>(T val) {
_value = val;
}
}
In Winform application I have a class with 2 properties and I want the user to be able to choose the type of those properties.
This is what I made so far:
Class with the properties:
static public class DataGridColumnData
{
public static object SearchColumn { get; set; }
public static object ResultColumn { get; set; }
}
And the user can choose the type of the properties using a Combobox with DropDownList Style which has values like
System.String
System.Double
System.Int32
System.Boolean
System.DateTime
Is there a way to make those properties to be types the ones that user chooses?
You can make your class generic:
static public class DataGridColumnData<T>
{
public static T SearchColumn { get; set; }
public static T ResultColumn { get; set; }
}
Then, in your code, you can create a class of the desired type:
object myDataGridColumnData;
if (userSelection == "String") {
myDataGridColumnData = new DataGridColumnData<string>();
} else if (userSelection == "Double") {
myDataGridColumnData = new DataGridColumnData<double>();
} ...
Note that, technically, DataGridColumnData<string> is a completely different type than DataGridColumnData<int>, so object is the only common supertype. Thus, to be able to access the values of myDataGridColumnData in code, you might need to use a dynamic variable or (prefered) use some common interface or base class that returns the values typed as objects.
There are ways to make the properties strongly typed in runtime using generics, but I am not sure how useful it is. Here is a solution either way:
Create an interface that is not strongly typed to facilitate interaction with the object:
public interface IDataGridColumnData
{
object SearchColumnAsObject { get; set; }
object ResultColumnAsObject { get; set; }
}
Create generic class that allows for the creation of strongly typed versions at runtime (and in code as well, of course), and that implements the interface:
public class DataGridColumnData<TSearch, TResult> : IDataGridColumnData
{
public TSearch SearchColumn { get; set; }
public static TResult ResultColumn { get; set; }
public object SearchColumnAsObject
{
get { return SearchColumn; }
set { SearchColumn = (TSearch)value; }
}
public object ResultColumnAsObject
{
get { return ResultColumn; }
set { ResultColumn = (TResult)value; }
}
}
Create a factory method that will manufacture strongly typed versions of the class, returning it as the object-typed interface:
private static IDataGridColumnData GetDataGridColumnData(
Type searchType, Type resultType)
{
var typedColumnDataType = typeof(DataGridColumnData<,>)
.MakeGenericType(new[] { searchType, resultType });
return (IDataGridColumnData)Activator.CreateInstance(typedColumnDataType);
}
...and put it to use:
IDataGridColumnData instance = GetDataGridColumnData(
Type.GetType("System.Int32"),
Type.GetType("System.String"));
// use the properties
instance.SearchColumnAsObject = 42; // works well
instance.SearchColumnAsObject = "42"; // throws exception
No, ther is not. A class is statically compiled. No wy to change the property for a static class at runtime.
You can create a subclass nd override it, via bytecode emission, though.
You can use the is keyword
if (x.SearchColumn is Double)
{
}
See also MSDN: Is (C# Reference)
I'm trying to implement a class to access items of different types, in a similar way to database rows.
However, I have two different ideas in mind, and I don't know which one to choose:
Design 1
public enum ObjectTypeA
{
Undefined,
Integer,
Float
}
public class MyObjectA
{
private object val;
public ObjectTypeA Type
{
get;
private set;
}
public int Integer
{
get
{
if (Type != ObjectTypeA.Integer) throw new Exception();
return (int)val;
}
set
{
Type = ObjectTypeA.Integer;
val = value;
}
}
public float Float
{
get
{
if (Type != ObjectTypeA.Float) throw new Exception();
return (float)val;
}
set
{
Type = ObjectTypeA.Float;
val = value;
}
}
}
Less compile-time checks possible.
Can't use the is operator, GetType(), etc. (reinvents the type system).
Boxing and unboxing for value types.
Can be inherited by other classes (e.g. I can create a "named object" using inheritance).
Design 2
public abstract class MyObjectB
{
}
public class MyIntegerB : MyObjectB
{
public int Value
{
get;
set;
}
public MyIntegerB(int _value)
{
Value = _value;
}
}
public class MyFloatB : MyObjectB
{
public float Value
{
get;
set;
}
public MyFloatB(float _value)
{
Value = _value;
}
}
Shorter and simpler implementation.
Very verbose (casting) to use.
Performance is not critical, but it's still important, since most of the objects that are going to be stored are integers or floats, so boxing overhead matters.
The classes will just contain the values, not methods that depend on the type, etc. so it doesn't matter if the solution uses inheritance.
IMPORTANT: One of the requirements is that there may be two types that use the same underlying type (e.g. two classes derived from MyObjectB may use int as the Value), so using object or generics may not be possible.
Any suggestion about which design to use, or another different design?
EDIT:
The reason I don't like the second one is because it's very verbose to use:
MyObjectB objB = new MyIntegerB(12);
Console.WriteLine(((MyIntegerB)objB).Value);
And because I can't inherit it to create something like a "named object", so I have to attach MyObjectB to the class, and the usage is even more verbose.
I don't see why you wouldn't use generics here. More strongly: I don't see why you need this at all: It seems like Nullable<T> would cover all of your use cases very nicely. If not, implementing this generically is trivial:
public class ValueWrapper<T>
{
public T Value
{
get;
private set;
}
public Type WrappedType
{
get { return typeof(T); }
}
}
public MySpecialInt : ValueWrapper<int>
{
/* etc */
}
why not use generics?
public abstract class MyObjectB<T>
{
public T Value
{
get;
set;
}
public MyObjectB(T _value)
{
Value = _value;
}
}
you only need one class at this point. just instantiate it differently:
var myObj = new MyObjectB<Int>(1);
or
var myObj = new MyObjectB<Float>(0.012);
I know you mentioned not wanting to deal with boxing and unboxing, but I still think a Generic class would be your best bet here.
public class MyObject<T>
{
public MyObject(T t) {
Value = t;
}
public T Value { get; set; }
}
Edit:
One of the requirements is that there
may be two types that use the same
underlying type (e.g. two classes
derived from MyObjectB may use int as
the Value), so using object or
generics may not be possible.
That would only apply if you're extending the class. There's no problem if you wrap the class instead, i.e. create a MyObject<int> and access its Value property, rather than subclassing it.
Having said that, if you want to subclass a generic class, the subclass would also need to be a generic class.
Have you considered generics?
public class MyObjectA<T> {
public T Value {
get; set;
}
}
I've written a similar class that could hold either a single instance of ClassX or an array of ClassX. The trick was that it could change during runtime, so a generic wouldn't suffice, but I still wanted it strong-typed in all cases. It sounds like that's similar to what you're trying to accomplish here.
I chose the first option, and here's why: Wherever possible, I encapsulate complexity within a class to make the class easier to use. Classes should encapsulate away complexity from the caller, making calls to it more concise. If using MyObjectB makes your code more verbose, than I don't think that's the right answer.
if you need heterogeneous collections then this would do.
public enum ObjectTypeA
{
Undefined,
Integer,
Float
}
public class MyObjectA
{
public MyObjectA(object value) : this(value, InfereType(value))
{ }
public MyObjectA(object value, ObjectTypeA type)
{
Value = value;
Type = type;
}
public object Value { get; private set; }
public ObjectTypeA Type
{
get;
private set;
}
public T ValueAs<T>()
{
return (T)Value;
}
}
then use it like
List<MyObjectA> list = GetAllValues();
foreach (var item in list)
{
switch (item.WrappedType)
{
case MyObjecttypeA.Float:
float f = item.ValueAs<float>();
// do something with float
}
}
I have a class that stores a serialized value and a type. I want to have a property/method returning the value already casted:
public String Value { get; set; }
public Type TheType { get; set; }
public typeof(TheType) CastedValue { get { return Convert.ChangeType(Value, typeof(_Type)); }
Is this possible in C#?
It's possible if the class containing the property is generic, and you declare the property using the generic parameter:
class Foo<TValue> {
public string Value { get; set; }
public TValue TypedValue {
get {
return (TValue)Convert.ChangeType(Value, typeof(TValue));
}
}
}
An alternative would be to use a generic method instead:
class Foo {
public string Value { get; set; }
public Type TheType { get; set; }
public T CastValue<T>() {
return (T)Convert.ChangeType(Value, typeof(T));
}
}
You can also use the System.ComponentModel.TypeConverter classes to convert, since they allow a class to define it's own converter.
Edit: note that when calling the generic method, you must specify the generic type parameter, since the compiler has no way to infer it:
Foo foo = new Foo();
foo.Value = "100";
foo.Type = typeof(int);
int c = foo.CastValue<int>();
You have to know the type at compile time. If you don't know the type at compile time then you must be storing it in an object, in which case you can add the following property to the Foo class:
public object ConvertedValue {
get {
return Convert.ChangeType(Value, Type);
}
}
Properties, events, constructors etc can't be generic - only methods and types can be generic. Most of the time that's not a problem, but I agree that sometimes it's a pain. Brannon's answer gives two reasonable workarounds.
I don't believe the example you've given here is possible. The type of CastedValue has to be defined at compile time, which means it can't depend on a runtime value (the value of the TheType property).
EDIT: Brannon's solution has some good ideas for how to handle this using a generic function rather than a property.