Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/297.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
如何用Newtonsoft.Json序列化C#ref字段?_C#_Json_Serialization_Json.net_Ref - Fatal编程技术网

如何用Newtonsoft.Json序列化C#ref字段?

如何用Newtonsoft.Json序列化C#ref字段?,c#,json,serialization,json.net,ref,C#,Json,Serialization,Json.net,Ref,假设我有一个这样的类: [JsonObject(MemberSerialization.OptIn)] public class TestClass { private readonly int _SomeField; [JsonProperty(nameof(InputInfo))] public ref readonly int SomeField => ref _SomeField; } 注意:这个类是一个简化的示例,在我的真实场景中,\u SomeFie

假设我有一个这样的类:

[JsonObject(MemberSerialization.OptIn)]
public class TestClass
{
    private readonly int _SomeField;

    [JsonProperty(nameof(InputInfo))]
    public ref readonly int SomeField => ref _SomeField;
}
注意:这个类是一个简化的示例,在我的真实场景中,
\u SomeField
字段不是成员字段,否则我只会在其上添加Json属性。该字段是由作为类成员的另一个对象公开的字段。公共属性只是向用户公开该字段,以便更容易访问该值

同样,实际属性tipe不是
int
,而是一个12字节的
结构
,因此我通过引用返回它,以避免无用的值复制

我正在使用
JsonConvert.serializedObject(这是Formatting.Indented)
序列化这样一个类

Json在转换值时抛出一个异常,表示它无法访问字段/属性值(我猜它是
ref
参数,使得库使用的反射过程崩溃)

我试着使用一个定制的
JsonConverter
,但是崩溃发生在使用任何额外的转换器之前

我知道一个快速的解决方案是添加一个二级私有参数,该参数只返回该字段作为值而不是引用,并且只用于Json序列化,但对我来说很糟糕(我还必须禁用关于未使用私有参数的自动VS警告),如果可能的话,我正在寻找一个更好的解决方案(不引入无用的字段/属性)


感谢您的帮助!

这太长了,不能作为评论,如果有人发布其他答案,我将删除它。快速查看一下,您现在无法覆盖它

问题发生在第110行:

public object GetValue(object target)
{
        try
        {
            if (_getter == null)
            {
                _getter = DynamicReflectionDelegateFactory.Instance.CreateGet<object>(_memberInfo);
            }

            return _getter(target); //Line 100
        }
        catch (Exception ex)
        {
            throw new JsonSerializationException("Error getting value from '{0}' on '{1}'.".FormatWith(CultureInfo.InvariantCulture, _memberInfo.Name, target.GetType()), ex);
        }
}

我找不到任何预先存在的问题,因此我建议报告此问题。问题链接在此处:感谢您的快速回复!是的,我担心它现在不受支持,我在此处创建了一个问题:
using System;
using System.Reflection;
using System.Reflection.Emit;

namespace ConsoleApp15
{
    public class TestClass
    {
        public TestClass()
        {
            _SomeField = 42;
        }

        private readonly int _SomeField;

        public ref readonly int SomeField => ref _SomeField;
    }

    internal class Program
    {
        private static void Main(string[] args)
        {
            var propertyInfo = typeof(TestClass).GetProperty("SomeField");
            var getMethod = CreateGet<object>(propertyInfo);

            TestClass obj = new TestClass();

            var result = getMethod(obj);
        }

        public static Func<T, object> CreateGet<T>(PropertyInfo propertyInfo)
        {
            DynamicMethod dynamicMethod = CreateDynamicMethod("Get" + propertyInfo.Name, typeof(object), new[] { typeof(T) }, propertyInfo.DeclaringType);
            ILGenerator generator = dynamicMethod.GetILGenerator();

            GenerateCreateGetPropertyIL(propertyInfo, generator);

            return (Func<T, object>)dynamicMethod.CreateDelegate(typeof(Func<T, object>));
        }

        private static DynamicMethod CreateDynamicMethod(string name, Type returnType, Type[] parameterTypes, Type owner)
        {
            DynamicMethod dynamicMethod = new DynamicMethod(name, returnType, parameterTypes, owner, true);

            return dynamicMethod;
        }

        private static void GenerateCreateGetPropertyIL(PropertyInfo propertyInfo, ILGenerator generator)
        {
            MethodInfo getMethod = propertyInfo.GetGetMethod(true);
            if (getMethod == null)
            {
                throw new ArgumentException("Property " + propertyInfo.Name + " does not have a getter.");
            }

            if (!getMethod.IsStatic)
            {
                generator.PushInstance(propertyInfo.DeclaringType);
            }

            generator.CallMethod(getMethod);
            generator.BoxIfNeeded(propertyInfo.PropertyType);
            generator.Return();
        }
    }

    internal static class ILGeneratorExtensions
    {
        public static void PushInstance(this ILGenerator generator, Type type)
        {
            generator.Emit(OpCodes.Ldarg_0);
            if (type.IsValueType)
            {
                generator.Emit(OpCodes.Unbox, type);
            }
            else
            {
                generator.Emit(OpCodes.Castclass, type);
            }
        }

        public static void PushArrayInstance(this ILGenerator generator, int argsIndex, int arrayIndex)
        {
            generator.Emit(OpCodes.Ldarg, argsIndex);
            generator.Emit(OpCodes.Ldc_I4, arrayIndex);
            generator.Emit(OpCodes.Ldelem_Ref);
        }

        public static void BoxIfNeeded(this ILGenerator generator, Type type)
        {
            if (type.IsValueType)
            {
                generator.Emit(OpCodes.Box, type);
            }
            else
            {
                generator.Emit(OpCodes.Castclass, type);
            }
        }

        public static void UnboxIfNeeded(this ILGenerator generator, Type type)
        {
            if (type.IsValueType)
            {
                generator.Emit(OpCodes.Unbox_Any, type);
            }
            else
            {
                generator.Emit(OpCodes.Castclass, type);
            }
        }

        public static void CallMethod(this ILGenerator generator, MethodInfo methodInfo)
        {
            if (methodInfo.IsFinal || !methodInfo.IsVirtual)
            {
                generator.Emit(OpCodes.Call, methodInfo);
            }
            else
            {
                generator.Emit(OpCodes.Callvirt, methodInfo);
            }
        }

        public static void Return(this ILGenerator generator)
        {
            generator.Emit(OpCodes.Ret);
        }
    }
}