3

私は ASP.NET MVC2 を使用しており、次のオブジェクト構造を持っています。

public class IDealer {
  string Name { get; set; }
  List<IVehicle> Vehicles { get; set; }
}

public class DealerImpl {
  public string Name { get; set; }
  public List<IVehicle> Vehicles { get; set; }
}

public interface IVehicle {
    string Type { get; }
}

public class Car : IVehicle {
    public string Type { get { return this.GetType().FullName; } }
}

public class Truck : IVehicle {
    public string Type { get { return this.GetType().FullName; } }
}

ページリクエストでオブジェクトを逆シリアル化する ModelBinder として次のクラスがあります。

public class JsonModelBinder : DefaultModelBinder {
    public override object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext) {
        return deserialize(controllerContext, bindingContext);
    }

    protected static bool IsJSONRequest(ControllerContext controllerContext) {
        var contentType = controllerContext.HttpContext.Request.ContentType;
        return contentType.Contains("application/json");
    }

    protected virtual object deserialize(ControllerContext controllerContext, ModelBindingContext bindingContext) {
        Type modelType = bindingContext.ModelMetadata.ModelType;

        bool isNotConcrete = bindingContext.ModelMetadata.ModelType.IsInterface || bindingContext.ModelMetadata.ModelType.IsAbstract;
        if (!IsJSONRequest(controllerContext)) {
            return base.BindModel(controllerContext, bindingContext);
        } else {
            var request = controllerContext.HttpContext.Request;
            var jsonStringData = new StreamReader(request.InputStream).ReadToEnd();
            if (isNotConcrete) {
                Dictionary<string, Object> result = JsonConvert.DeserializeObject<Dictionary<string, Object>>(jsonStringData);
                string type = result["Type"] as string;
                modelType = Type.GetType(type + ",MyCompany.Common");
            }

            return JsonConvert.DeserializeObject(jsonStringData, modelType, new JsonSerializerSettings { TypeNameHandling = TypeNameHandling.Auto });
        }       
    }
}

// ASP.NET MVC Controller
protected override void Initialize(System.Web.Routing.RequestContext requestContext) {
  base.Initialize(requestContext);
  ModelBinders.Binders.DefaultBinder = new JsonModelBinder();
}

[HttpPost]
public ActionResult addUpdateDealer(IDealer dealer) {
  // breaks before here with the error in the comment below
}

// and in the aspx page
<script>
var model = <%= JsonConvert.SerializeObject(Model, Formatting.None, new JsonSerializerSettings { TypeNameHandling = TypeNameHandling.Auto }) %>;
</script>

私が直面している問題は、コードが IVehicles の子リストを逆シリアル化しようとするときに、インスタンス化する車両のタイプがわからないことです。どのクラスをインスタンス化するかを決定するために使用できる「Type」という名前の IVehicle にプロパティを配置しましたが、このチェックを実行するためにオーバーライドを提供する方法/場所/方法がわかりません。

4

1 に答える 1

1

あなたのソリューションは、現在 TypeNameHandling と呼ばれる JSON.NET に組み込まれているものに似ています。これに関するリリースノートは次のとおりです

JSON メッセージには$typeプロパティを含める必要があります。このプロパティは逆シリアル化されませんが、使用する具象型としてデシリアライザーによって解釈されます。

于 2012-06-19T21:33:18.790 に答える