Polymorphism for both function inputs and outputs

元气小坏坏 提交于 2019-12-24 10:09:53

问题


Polymorphism for inputs was solved using functional idiomatic approach and now looking forward to solve it for return types that involved a JSON serializer which actually demands to know the type of the record.

Input parameters were enforced to have some specific fields as mandatory and the solution allowed to pass different types as long as the field members existed. Solution was referred to as SRTP or structural (or duck) typing.

Now I've a roadblock where this function is essentially a web service call which returns the latest JSON schema based on the type of the object passed. I pass in mandatory fields (Registration, Owner, Wheels) only and the server returns the original mandatory data along with the custom fields and both types (Car, Truck) have different kinds of JSON schemas.

The block is with JSON serializer that needs to know the type of the object being passed and the type has to be hard coded in order to serialize.

So in a way function has both polymorphic inputs and outputs.

type Car = {
    Registration: string
    Owner: string
    Wheels: int
    customAttribute1: string
    customAttribute2: string
}

type Truck = {
   Registration: string
   Owner: string
   Wheels: int
   customField5: string
   customField6: string
}


let inline someComplexFun v  =
    let owner =  (^v: (member Owner: string)(v)) 
    let registration = (^v: (member Registration: string)(v))
    // send the mandatory fields to server to fetch rest of the custom fields.

    use response = request.GetResponse() :?> HttpWebResponse
    use reader = new StreamReader(response.GetResponseStream())
    use memoryStream = new MemoryStream(Encoding.UTF8.GetBytes(reader.ReadToEnd()))
    (new DataContractJsonSerializer(typeof<Car>)).ReadObject(memoryStream) :?> Car

Now this last line essentially will change if Truck type was passed

(new DataContractJsonSerializer(typeof<Truck>)).ReadObject(memoryStream) :?> Truck

Note: Now If there's a lateral approach using a different functional idiomatic way, I'm flexible to choose a different path. As long as function can not only receive and return these two specific types.

P.S. Is reflection an answer to this?


回答1:


If necessary, you can check the type info and pass that on. Since you are already using typeof, you can use that on v as well. If we remain within the same example:

type Vehicle = {
    Registration: string
    Owner: string
    VehicleType: System.Type
}

let inline someComplexFun v  =
   let t = typeof<'v>
   let owner =  (^v: (member Owner: string)(v)) 
   let registration = (^v: (member Registration: string)(v))
   {Registration = registration; Owner = owner; VehicleType = t}

You could use t to identify which serializer to apply or extract it from the VehicleType field.



来源:https://stackoverflow.com/questions/49567600/polymorphism-for-both-function-inputs-and-outputs

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!