Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/258.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# 基于Json反序列化的Convert类_C#_Serialization_Json.net_Json Deserialization - Fatal编程技术网

C# 基于Json反序列化的Convert类

C# 基于Json反序列化的Convert类,c#,serialization,json.net,json-deserialization,C#,Serialization,Json.net,Json Deserialization,在我的应用程序中有一个类CoupledType,该类在类型为UserObject的较大对象中使用,它的实例通过使用Json.NET序列化保存在数据库中 这个类需要大量的重构,以便在更多的上下文中工作。它的名字也不理想,我想把它搬到另一个图书馆。但是,它仍然会扩展相同的基类,关键是,当用户反序列化他们保存的工作时,必须转换原始实例。 当前状态下的类大致如下所示: namespace FirstLibrary.Objects { [DataContract] public class

在我的应用程序中有一个类
CoupledType
,该类在类型为
UserObject
的较大对象中使用,它的实例通过使用Json.NET序列化保存在数据库中

这个类需要大量的重构,以便在更多的上下文中工作。它的名字也不理想,我想把它搬到另一个图书馆。但是,它仍然会扩展相同的基类,关键是,当用户反序列化他们保存的工作时,必须转换原始实例。

当前状态下的类大致如下所示:

namespace FirstLibrary.Objects
{
    [DataContract]
    public class CoupledType : BaseType
    {
        [DataMember]
        public double CoupledValue { get; set; } 
    }
}
namespace SecondLibrary.Objects
{
    [DataContract]
    public class DecoupledType : BaseType
    {
        [DataMember]
        GenericContract Contract { get; set; }
    }
}
[DataContract]
public class GenericContract
{
    [DataMember]
    public ContractType ContractType { get; set; }

    [DataMember]
    public double ContractValue { get; set; }
}
我要将其转换为的类型如下所示:

namespace FirstLibrary.Objects
{
    [DataContract]
    public class CoupledType : BaseType
    {
        [DataMember]
        public double CoupledValue { get; set; } 
    }
}
namespace SecondLibrary.Objects
{
    [DataContract]
    public class DecoupledType : BaseType
    {
        [DataMember]
        GenericContract Contract { get; set; }
    }
}
[DataContract]
public class GenericContract
{
    [DataMember]
    public ContractType ContractType { get; set; }

    [DataMember]
    public double ContractValue { get; set; }
}
上面提到的
GenericContract
类如下所示:

namespace FirstLibrary.Objects
{
    [DataContract]
    public class CoupledType : BaseType
    {
        [DataMember]
        public double CoupledValue { get; set; } 
    }
}
namespace SecondLibrary.Objects
{
    [DataContract]
    public class DecoupledType : BaseType
    {
        [DataMember]
        GenericContract Contract { get; set; }
    }
}
[DataContract]
public class GenericContract
{
    [DataMember]
    public ContractType ContractType { get; set; }

    [DataMember]
    public double ContractValue { get; set; }
}
在转换过程中,我希望创建一个新的
GenericContract
对象,从其他地方获取
ContractType
(在这个转换中,它的值总是相同的),并且
ContractValue
将被设置为
CoupledType
中原始
CoupledValue
的值

可能更棘手的部分是,我需要访问此对象的父对象
UserObject
(即它从中反序列化的对象),以获取对
ContractType
值的引用


总而言之,我需要为Json.NET编写一个转换器,该转换器执行以下操作:

  • 将对象的类型名称从
    FirstLibrary.Objects.CoupledType
    更改为
    SecondLibrary.Objects.DecoupledType
  • GenericContract
    替换
    double-CoupledValue
    (其构造需要访问
    ParentObject
    CoupledType
    实例是其成员/正从其反序列化)
我没有在Json中转换类型的很多经验(已经编写了
Json.Net
JsonConverter
的子类,将大量
double
对象转换为
double[]
s。我没有更改类型或属性名称的经验。如果有人能至少为我指出一个可能的解决方案,我将不胜感激


现有的样本(推测性,在BSON中实际序列化)

如果有帮助,序列化设置如下所示:

ConstructorHandling = ConstructorHandling.AllowNonPublicDefaultConstructor,
TypeNameHandling = TypeNameHandling.All

我不确定这些方法是否会无法满足一些未提及的要求,但我可以想出一些可能的方法,将
解耦类型
从电线连接到控制器中

您可以创建自定义的
HttpParameterBinding
,并在其中执行映射。传入的参数信息存储在
HttpParameterDescriptor
中,您可以查询参数以确定是否应用特定绑定

public class GenericContractBinding : HttpParameterBinding
{
   public GenericContractBinding(HttpParameterDescriptor descriptor) : base(descriptor){}
   public override Task ExecuteBindingAsync(ModelMetadataProvider provider, HttpActionContext context, CancellationToken cancellationToken)
   {
      if(context.ControllerContext.Configuration.DependencyResolver != null)
      {
         //This is a naive eval based only on the incoming type. You'll likely want to map
         var bazinga = context.Request.GetDependencyScope().GetService(Descriptor.ParameterType);
         if(bazinga.GetType() == typeof(GenericContract)
            context.ActionArguments[Descriptor.ParameterName] = bazinga;
      }
   }
}
或者,您也可以创建自定义Web API
ModelBinder
,并使用
ModelBinderAttribute
装饰您的类型(或者在route方法上显式声明绑定器提供程序)

公共类解耦TypeModelBinder:IModelBinder
{
public bool BindModel(System.Web.Http.Controllers.HttpActionContext actionContext,ModelBindingContext bindingContext)
{
//我假设您的JSON是在请求内容中发送的
字符串内容=actionContext.Request.content.ReadAsStringAsync().Result;
var json=JArray.Parse(content);//您真的应该切换到“默认数组”处理;其中的项数是一个实现细节。
//在我看来,这个“ContractTypeService”是在CompositionRoot中注入的,它将位于IHttpControllerActivator中
var contractType=actionContext.RequestContext.Configuration.DependencyResolver.GetService(typeof(ContractTypeService)).GetAmbientContractType();
列表合同=新列表();
foreach(json.Children()中的var项)
{    
var合同=新的通用合同();
contract.ContractValue=(双)项[“ContractValue”].Value();
contract.ContractType=ContractType;
合同。添加(合同);
}
}
//YMMV;您可以在这里强制执行对奇点的严格要求,或者在线路上有多个入站时执行其他操作
DecoupledType模型=新的DecoupledType()
{
Contract=contracts.Single()
};
bindingContext.Model=Model;
}
}
公共类解耦TypeModelBinderProvider:ModelBinderProvider
{
公共覆盖IModelBinder GetBinder(System.Web.Http.HttpConfiguration配置,类型modelType)
{
返回新的解耦TypeModelBinder();
}
}
…(在控制器中)
公共动态帖子([ModelBinder(typeof(DecoupledTypeModelBinderProvider))]decoupledTypeBazinga)
{
var合同=bazinga.合同;
var contractType=contract.contractType;
var contractValue=contract.contractValue;
}

希望这能让你走上成功之路。

你能提供一个紧凑的小样本,说明你想要什么以及哪里出了问题吗?更新了问题,希望有一个更清晰的问题定义。谢谢!发布一个样本序列化json,以及你想看到的反序列化表单。这确实很混乱。正常的反序列化是自动的。只需确保您的
UserObject
的属性指向正确的库,然后以下操作就可以
JsonConvert.DeserializeObject(json);
使用json引用字符串。