Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/305.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# Can';t Json.NET是否仅使用隐式运算符自动处理值类型?_C#_.net_Json.net - Fatal编程技术网

C# Can';t Json.NET是否仅使用隐式运算符自动处理值类型?

C# Can';t Json.NET是否仅使用隐式运算符自动处理值类型?,c#,.net,json.net,C#,.net,Json.net,以下是我的微小自定义值类型类: public struct PhoneNumber { private readonly string _phoneNumber; public PhoneNumber(string phoneNumber) { _phoneNumber = phoneNumber; // ... lots more will happen here to validate the phone number }

以下是我的微小自定义值类型类:

public struct PhoneNumber
{
    private readonly string _phoneNumber;

    public PhoneNumber(string phoneNumber)
    {
        _phoneNumber = phoneNumber;
        // ... lots more will happen here to validate the phone number
    }

    public static implicit operator PhoneNumber(string phoneNumber)
    {
        return new PhoneNumber(phoneNumber);
    }

    public static implicit operator string(PhoneNumber phoneNumber)
    {
        return phoneNumber.ToString();
    }

    public override string ToString()
    {
        return _phoneNumber;
    }
}
使用字符串的隐式运算符和重写的ToString方法,我希望Json.NET能够序列化和反序列化此类的实例

然而,这样做:

 var pn = new PhoneNumber("1234567890");
 var json = JsonConvert.SerializeObject(pn);
。。。只返回一个空的
{}

我不希望将属性应用于我的值类型类或实现自定义序列化器

有没有其他约定可以让Json.NET按照我喜欢的方式运行?

C#是强类型语言。然而,人们通常在任何地方都使用
string
值。在这种情况下,强类型语言的起源并没有帮助。这样的问题被称为

.NET提供了
TypeConverter
来在不同类型之间转换值
Newtonsoft.Json
隐式使用类型转换器

我提出了这样的解决方案:

强类型接口

首先,我们定义接口来包装原语值

/// <summary>
/// Interface to make values strongly-typed with help of TypeConverters.
/// </summary>
/// <typeparam name="TInnerType">Inner type</typeparam>
public interface IStronglyTyped<out TInnerType>
{
    /// <summary>
    /// Inner value.
    /// </summary>
    TInnerType Value { get; }
}
不幸的是,这还不够。您必须为任何自定义类型的每个属性注册自定义转换。这要复杂得多。

我注意到列表底部提到了“TypeConverter”:

然后我制作了一个非常简单的自定义类型转换器:

[TypeConverter(typeof(Converter))]
public class PhoneNumber
{
    private readonly string _phoneNumber;

    public PhoneNumber(string phoneNumber)
    {
        _phoneNumber = _phoneNumber;
    }

    public static implicit operator PhoneNumber(string phoneNumber)
    {
        return new PhoneNumber(phoneNumber);
    }

    public static implicit operator string(PhoneNumber phoneNumber)
    {
        return phoneNumber.ToString();
    }

    public override string ToString()
    {
        return _phoneNumber;
    }

    public class Converter : TypeConverter
    {
        public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType)
        {
            return sourceType == typeof(string);
        }

        public override bool CanConvertTo(ITypeDescriptorContext context, Type destinationType)
        {
            return destinationType == typeof(string);
        }

        public override object ConvertTo(ITypeDescriptorContext context, CultureInfo culture, object value, Type destinationType)
        {
            return value.ToString();
        }
    }
}
现在,如果我有一个带有自定义PhoneNumber属性的类,它将按我希望的方式序列化:

public class MyClass
{
    public PhoneNumber PhoneNumber { get; set; }
}
序列化:

var x = new MyClass
{
    PhoneNumber = new PhoneNumber("1234567890")
};

var json = JsonConvert.SerializeObject(x);
输出:

{ "PhoneNumber": "1234567890" }

您的类没有任何属性,因此它将序列化为空对象。隐式运算符不会影响Newtonsoft序列化。您需要一个自定义类型转换器来将类序列化为字符串。您是否试图避免原始类型的困扰,并使用强类型而不是字符串?@VladimirSerykh,是的,完全正确。:)@glenebob结构是c#中的值类型。结构/对象/值类型/引用类型无关紧要。该结构没有公共属性,因此没有可序列化的内容。如果需要实体框架核心的代码段,请Ping me。这是一个很好的答案,而且非常详细。谢谢。:)没错,
TypeConverter
。使用我的解决方案,您可以将
Guid
Uri
包装到
IStronglyTyped
中,以提供额外的验证和更具体的类型。这种固定的原语困扰不仅适用于
字符串
值,也适用于其他常用的“原语”类型。@VladimirSerykh谢谢。你比我快了3分钟。非常令人印象深刻。
[TypeConverter(typeof(Converter))]
public class PhoneNumber
{
    private readonly string _phoneNumber;

    public PhoneNumber(string phoneNumber)
    {
        _phoneNumber = _phoneNumber;
    }

    public static implicit operator PhoneNumber(string phoneNumber)
    {
        return new PhoneNumber(phoneNumber);
    }

    public static implicit operator string(PhoneNumber phoneNumber)
    {
        return phoneNumber.ToString();
    }

    public override string ToString()
    {
        return _phoneNumber;
    }

    public class Converter : TypeConverter
    {
        public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType)
        {
            return sourceType == typeof(string);
        }

        public override bool CanConvertTo(ITypeDescriptorContext context, Type destinationType)
        {
            return destinationType == typeof(string);
        }

        public override object ConvertTo(ITypeDescriptorContext context, CultureInfo culture, object value, Type destinationType)
        {
            return value.ToString();
        }
    }
}
public class MyClass
{
    public PhoneNumber PhoneNumber { get; set; }
}
var x = new MyClass
{
    PhoneNumber = new PhoneNumber("1234567890")
};

var json = JsonConvert.SerializeObject(x);
{ "PhoneNumber": "1234567890" }