Showing posts with label generics. Show all posts
Showing posts with label generics. Show all posts

Wednesday, August 1, 2018

Custom Jackson serializer for a generic tree

Leave a Comment

Say I have a parametrized tree implemented in Java as follows:

public class Tree<E> {    private static class Node {       E element;       List<Node> children.    }     Node root;     //... You get the idea. } 

The idea here is that the implementation above is only concerned with the topology of the tree, but does not know anything about the elements that will be stored in the tree by an instantiation.

Now, say I want my tree elements to be geographies. The reason they are organized in trees is because continents contain countries, countries contain states or a provinces, and so on. For simplicity, a geography has a name and a type:

public class GeoElement { String name; String type; } 

So that, finally, the geo hierarchy looks like so:

public class Geography extends Tree<GeoElement> {} 

Now to Jackson serialization. Assuming the Jackson serializer can see the fields, the direct serialization of this implementation will look like this:

{    "root": {       "element": {          "name":"Latin America",          "type":"Continent"       }       "children": [           {              "element": {                 "name":"Brazil",                 "type":"Country"              },              "children": [                  // ... A list of states in Brazil              ]           },           {              "element": {                 "name":"Argentina",                 "type":"Country"              },              "children": [                  // ... A list of states in Argentina              ]           }       ]    } 

This JSON rendering is no good because it contains the unnecessary artifacts from the Tree and Node classes, i.e. "root" and "element". What I need instead is this:

{    "name":"Latin America",    "type":"Continent"    "children": [        {           "name":"Brazil",           "type":"Country"           "children": [              // ... A list of states in Brazil           ]        },        {           "name":"Argentina",           "type":"Country"           "children": [              // ... A list of states in Argentina           ]        }    ] } 

Any help is most appreciated. -Igor.

4 Answers

Answers 1

What you need is @JsonUnwrapped.

Annotation used to indicate that a property should be serialized "unwrapped"; that is, if it would be serialized as JSON Object, its properties are instead included as properties of its containing Object

Add this annotation to the root field of Tree & element field of Node classes as follows:

public class Tree<E> {    private static class Node {        @JsonUnwrapped       E element;       List<Node> children.    }     @JsonUnwrapped    Node root;     //... You get the idea. } 

And it will give you your desired output:

{     "name": "Latin America",     "type": "Continent",     "children": [{         "name": "Brazil",         "type": "Country",         "children": []     }, {         "name": "Argentina",         "type": "Country",         "children": []     }] } 

Answers 2

Perhaps use @JsonValue like so:

public class Tree<E> {   @JsonValue   Node root; } 

if all you need is to just "unwrap" your tree?

Answers 3

Your best bet will be to build and register a custom serializer for your objects.

Define your serializer:

public class NodeSerializer extends StdSerializer<Node> { 

Then on your Node class:

@JsonSerialize(using = NodeSerializer.class) public class Node { } 

And inside of the NodeSerializer

@Override     public void serialize(       Node node, JsonGenerator jgen, SerializerProvider provider)        throws IOException, JsonProcessingException {          jgen.writeStartObject();         jgen.writeStringField("name", node.element.name);          jgen.writeStringField("type", node.element.type);         //Process children         serializeFields(node, jgen, provider);         jgen.writeEndObject();     } 

This general framework will let you control how the elements get serialized. You may need to @JsonIgnore the element object inside of the Node as well since your custom serializer is taking care of pushing that info into the resulting JSON. There is a lot online about custom serializers and overriding default JSON export.

You can get rid of root in a similar way with a serializer for the Tree implementation.

If you don't want to register the serializer on the class you can also do it on a one at a time basis using the ObjectMapper:

ObjectMapper mapper = new ObjectMapper();  SimpleModule module = new SimpleModule(); module.addSerializer(Node.class, new NodeSerializer()); mapper.registerModule(module);  String serialized = mapper.writeValueAsString(tree); 

The annotation approach will apply globally. This approach allows some control of how/where your custom serializer is used.

Answers 4

For removing the element type, one possibility would be to change your structure so that the name and the type will be directly included in each node:

public class TreeGeo {    private static class Node {       String name;       String type;       List<Node> children.    }     Node root; } 

For removing the root type, I don't know. I suppose that you could extract a sub-object from the jsonObject but I don't know much about Jackson. However, you could give it a better name like world or manipulate the resulting string to remove it manually with some string manipulations.

Read More

Friday, April 13, 2018

Using a type to instantiate a derived class which uses restricted generics

Leave a Comment

I'm using a generic factory class where the generic part is the derived class that is being used. The normal usage is clear: BaseClass<DerivedA> C = new BaseClass<DerivedA>(). Now though I'm trying to put in property injection into the class where I use these classes. To do that I tried to give Type as a Parameter (so that I can inject which derived class is being used).

Now though I'm a bit at a loss despite looking for examples and trying around myself. And I'm now wondering: Is such a construct possible at all to use? And if so how can I instantiate the class and use Exists and ExistsB?

Usage:

public class MyMainClass {     object _ClassInstance; // BaseClass<DerivedA> or BaseClass<DerivedB>      public MyyMainClass(Type typeIWant)     {           .....     } }  .... MyMainClass a = new MyMainClass(typeof(DerivedA)); MyMainClass b = new MyMainClass(typeof(DerivedB)); 

Generic class:

public abstract class BaseClass<T> where T: BaseClass<T>, new() { ...     public bool Exists(int a) {...} } 

Derived class:

public class DerivedA :BaseClass<DerivedA> { ... }  public class DerivedB :BaseClass<DerivedB> { ...    public bool ExistsB(string a) {...} } 

4 Answers

Answers 1

You can create an instance of any type you pass with this:

_ClassInstance = Activator.CreateInstance(typeIWant) 

It isn't recommended though, because you will be forever checking its type and casting it when you want to use one of the BaseClass methods. If you are able to change your main class to take a type parameter, it should look like this:

public class MyMainClass<T> where T: BaseClass<T>, new() {     T _ClassInstance; // BaseClass<DerivedA> or BaseClass<DerivedB>      public MyMainClass()     {         _ClassInstance = new T();     } } 

This will allow you to use any methods defined on BaseClass. Given you want to use ExistsB, which isn't, you will still need to check its type at run-time and cast it. I would recommend something like this:

if (_ClassInstance is DerivedB derivedB)     derivedB.ExistsB("..."); 

If you really need compile-time checking, and I would recommend it, your classes will need to change. You can't access a method or property defined on a derived class with a reference to the base class only.

Answers 2

Is this what you want?

Object instance1 = Activator.CreateInstance<Object>(); Object instance2 = Activator.CreateInstance(typeof(object)); 

Answers 3

I recommend you to use getType to take a type name. In case of you level up the inheritance (inherit another class from DerivedB etc), If you use getType you can be sure that you call this method for only for the instances of DerivedB types.

MyMainClass b = new MyMainClass(typeof(DerivedB));  if(b.GetType() == typeof(DerivedB))  b.ExistsB(...); 

Answers 4

This is main problem of abstract classes - you share interface AND implementation. But in your case, you strongly depend on different interfaces. To simplify problem, just look at what you actually want:

public interface IExistable<in TValue> {     bool Exists(TValue value); }  public interface IDerivedA : IExistable<int> { }  public interface IDerivedB : IExistable<int>, IExistable<string> { } 

As you can see, you overcomplicating IDerivedB with two interfaces, that said, your MainClass depends on IDerivedB on some occasions. It is not bad to extend interface, you just using it wrong. So what you must do, is define interface for your MainClass:

public interface IMainClass {     //some methods here } 

And create two implementations:

public class ConcreteMainClass : CommonMainClass //you can derive from common, delegate to inner instance or implement interface from scratch - you decide depending on situation {     private readonly IDerivedB _instance;     public ConcreteMainClass(IDerivedB instance) : base(instance)     {         _instance = instance;     }      //you can override some logic here depending on IExistable<string> from IDerivedB }  public class CommonMainClass : IMainClass {     private readonly IExistable<int> _instance;     public CommonMainClass(IExistable<int> instance)     {         _instance = instance;     }      //this is where you don't depend on IExistable<string> } 

This way you can write more clear code:

IMainClass a = new CommonMainClass(new DerivedA()); IMainClass b = new ConcreteMainClass(new DerivedB()); 

PS: It is better to pass dependencies to upper level of class life cycle, instead of activating it inside, so you can use factory which will create them for you or even Dependency Injection.

PS2: Use interfaces before abstract classes. Interfaces/Constructors/Methods describes your overall dependencies. Abstract classes on the other hand is just a way to reuse implementation - they are not meant to define interface or how you work with class, you can make entire body private/protected without sharing anything out.

Read More

Saturday, January 20, 2018

Dispatch issue with generic subclass of custom table view controller

Leave a Comment

My application has a common base class for all table controllers, and I'm experiencing a strange bug when I define a generic subclass of that table controller base class. The method numberOfSections(in:) never gets called if and only if my subclass is generic.

Below is the smallest reproduction I could make:

class BaseTableViewController: UIViewController {   let tableView: UITableView    init(style: UITableViewStyle) {     self.tableView = UITableView(frame: .zero, style: style)      super.init(nibName: nil, bundle: nil)   }    required init?(coder aDecoder: NSCoder) {     fatalError("init(coder:) has not been implemented")   }    // MARK: - Overridden methods    override func viewDidLoad() {     super. viewDidLoad()      self.tableView.frame = self.view.bounds     self.tableView.delegate = self     self.tableView.dataSource = self      self.view.addSubview(self.tableView)   } }  extension BaseTableViewController: UITableViewDataSource {   func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {     return 0   }    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {     return UITableViewCell(style: .default, reuseIdentifier: nil)   } }  extension BaseTableViewController: UITableViewDelegate { } 

Here's the very simple generic subclass:

class ViewController<X>: BaseTableViewController {   let data: X    init(data: X) {     self.data = data     super.init(style: .grouped)   }    required init?(coder aDecoder: NSCoder) {     fatalError("init(coder:) has not been implemented")   }    func numberOfSections(in tableView: UITableView) -> Int {     // THIS IS NEVER CALLED!     print("called numberOfSections")     return 1   }    override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {     print("called numberOfRows for section \(section)")     return 2   }    override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {     print("cellFor: (\(indexPath.section), \(indexPath.row))")     let cell = UITableViewCell(style: .default, reuseIdentifier: nil)     cell.textLabel!.text = "foo \(indexPath.row) \(String(describing: self.data))"      return cell   }    func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {     print("didSelect: (\(indexPath.section), \(indexPath.row))")     self.tableView.deselectRow(at: indexPath, animated: true)   } } 

If I create a simple app that does nothing but display ViewController:

@UIApplicationMain class AppDelegate: UIResponder, UIApplicationDelegate {   var window: UIWindow?    func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {     self.window = UIWindow(frame: UIScreen.main.bounds)      let nav = UINavigationController(rootViewController: ViewController(data: 3))     self.window?.rootViewController = nav     self.window?.makeKeyAndVisible()     return true   } } 

The table draws correctly but numberOfSections(in:) is never called! As a result, the table only shows one section (presumably because, according to the docs, UITableView uses 1 for this value if the method isn't implemented).

However, if I remove the generic declaration from the class:

class ViewController: CustomTableViewController {   let data: Int    init(data: Int) {   ....   }    // ... } 

then numberOfSections DOES get called!

This behavior doesn't make any sense to me. I can work around it by defining numberOfSections in CustomTableViewController and then having ViewController explicitly override that function, but that doesn't seem like the correct solution: I would have to do it for any method in UITableViewDataSource that has this problem.

3 Answers

Answers 1

This is a bug / shortcoming within the generic subsystem of swift, in conjunction with optional (and therefore: @objc) protocol functions.

Solution first

You'll have to specify @objc for all the optional protocol implementations in your subclass. If there is a naming difference between the Objective C selector and the swift function name, you'll also have to specify the Objective C selector name in parantheses like @objc (numberOfSectionsInTableView:)

@objc (numberOfSectionsInTableView:) func numberOfSections(in tableView: UITableView) -> Int {     // this is now called!     print("called numberOfSections")     return 1 } 

For non-generic subclasses, this already has been fixed in Swift 4, but obviously not for generic subclasses.

Reproduce

You can reproduce it quite easy in a playground:

import Foundation  @objc protocol DoItProtocol {     @objc optional func doIt() }  class Base : NSObject, DoItProtocol {     func baseMethod() {         let theDoer = self as DoItProtocol         theDoer.doIt!() // Will crash if used by GenericSubclass<X>     } }  class NormalSubclass : Base {     var value:Int      init(val:Int) {         self.value = val     }      func doIt() {         print("Doing \(value)")     } }  class GenericSubclass<X> : Base {     var value:X      init(val:X) {         self.value = val     }      func doIt() {         print("Doing \(value)")     } } 

Now when we use it without generics, everything works find:

let normal = NormalSubclass(val:42) normal.doIt()         // Doing 42 normal.baseMethod()   // Doing 42 

When using a generic subclass, the baseMethod call crashes:

let generic = GenericSubclass(val:5) generic.doIt()       // Doing 5 generic.baseMethod() // error: Execution was interrupted, reason: signal SIGABRT. 

Interestingly, the doIt selector could not be found in the GenericSubclass, although we just called it before:

2018-01-14 22:23:16.234745+0100 GenericTableViewControllerSubclass[13234:3471799] -[TtGC34GenericTableViewControllerSubclass15GenericSubclassSi doIt]: unrecognized selector sent to instance 0x60800001a8d0 2018-01-14 22:23:16.243702+0100 GenericTableViewControllerSubclass[13234:3471799] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[TtGC34GenericTableViewControllerSubclass15GenericSubclassSi doIt]: unrecognized selector sent to instance 0x60800001a8d0'

(error message taken from a "real" project)

So somehow the selector (e.g. Objective C method name) cannot be found. Workaround: Add @objc to the subclass, as before. In this case we don't even need to specify a distinct method name, since the swift func name equals the Objective C selector name:

class GenericSubclass<X> : Base {     var value:X      init(val:X) {         self.value = val     }      @objc     func doIt() {         print("Doing \(value)")     } }  let generic = GenericSubclass(val:5) generic.doIt()       // Doing 5 generic.baseMethod() // Doing 5  

Answers 2

If you provide default implementations of the delegate methods (numberOfSections(in:), etc.) in your base class and override them in your subclasses where appropriate, they will be called:

extension BaseTableViewController: UITableViewDataSource {   func numberOfSections(in tableView: UITableView) -> Int {     return 1   }   ...  class ViewController<X>: BaseTableViewController {   ...   override func numberOfSections(in tableView: UITableView) -> Int {     // now this method gets called :)     print("called numberOfSections")     return 1   }   ... 

An alternative approach would be to develop your base class based on UITableViewController which already brings most of the things you need (a table view, delegate conformance, and default implementations of the delegate methods).

EDIT

As pointed out in the comments, the main point of my solution is of course what the OP explicitly didn't want to do, sorry for that... in my defense, it was a lengthy post ;) Still, until someone with a deeper understanding of Swift's type system comes around and sheds some light on the issue, I'm afraid that it still is the best thing you can do if you don't wand to fall back to UITableViewController.

Answers 3

Replace your init with coder method:

required init?(coder aDecoder: NSCoder) {    super.init(coder: aDecoder) } 

Actually if you have your cell created in Storyboard - I believe that it should be attached to tableView on which you try to create it. And you can remove both of your init methods if you do not perform any logic there.

Greetings from Germany

Read More

Thursday, December 14, 2017

Why is generic required when all types are already defined?

Leave a Comment

The exercise was to write my own map() function over Collection (without using any functional primitives, such as reduce()). It should handle a case such as this:

func square(_ input: Int) -> Int {             return input * input         } let result = input.accumulate(square) // [1,2,3] =>  [1,4,9] 

My first attempt was:

extension Collection {     func accumulate(_ transform: (Element) -> Element) -> [Element] {          var array: [Element] = []         for element in self {             array.append(transform(element))         }         return array     } }     

This works fine in a playground, but fails to build against the tests, giving an error:

Value of type '[Int]' has no member 'accumulate' 

The solution is to genericize the accumulate method:

extension Collection {     func accumulate<T>(_ transform: (Element) -> T) -> [T] {          var array: [T] = []         for element in self {             array.append(transform(element))         }         return array     } }     

I recognize that the generic version is less restrictive (doesn't require the transform to return same type), but given that the tests don't require this generality, why does the compiler?

Out of curiousity I tried:

extension Collection {     func accumulate<Element>(_ transform: (Element) -> Element) -> [Element] {          var array: [Element] = []         for element in self {             array.append(transform(element))         }         return array     } }     

which throws the fascinating build error: '(Self.Element) -> Element' is not convertible to '(Element) -> Element' at the append() statement.

So the compiler (of course) knows that the first Element is Self.Element, but doesn't treat the other Element type as the same. Why?


UPDATE:

Based on the answers, it appears that the rejection of the first version was a compiler bug, fixed in XCode 9.2 (I'm on 9.1).

But still I wondered whether in

func accumulate(_ transform: (Element) -> Element) -> [Element] 

it would see two types (Self.Element and Element) or recognize that they're the same.

So I did this test:

let arr = [1,2,3] arr.accumulate {     return String(describing: $0) } 

Sure enough, got the expected error: error: cannot convert value of type 'String' to closure result type 'Int'

So the correct answer is: the compiler will treat references to Element as the same, as long as there isn't a generic type that overloads the name.

Oddly, though, this succeeds:

[1,2,3].accumulate {     return String(describing: $0) } 

PS. Thanks to everyone for your input!

5 Answers

Answers 1

The original build error was a compiler error. In fact, the compiler will recognize that all instances of Element are the same, as long Element hasn't been overloaded as a generic type on the function.

Answers 2

  • About the first question, working with Xcode 9.2 and Swift 4 I didn't receive any building error such as:

Value of type '[Int]' has no member 'accumulate'

so doing this:

var mystuff:[Int] = [1,2,3] let result = mystuff.accumulate(square) 

it's just giving me the correct result [1,4,9]

  • For the second question, the function prototype is wrong, you should try this (with Self.Element):

    extension Collection {   func accumulate<Element>(_ transform: (Self.Element) -> Element) -> [Element] {     var array: [Element] = []     for element in self {       array.append(transform(element))     }     return array    } } 

Answers 3

I'll focus on your second question.

func accumulate<Element>(_ transform: (Element) -> Element) -> [Element] 

The trouble with writing this signature is you've got two different types with the same name.

  • The first type is Element which is your generic type (the bit between the angle brackets).
  • The second type is Self.Element, that is, the type of the elements in your collection, declared by the protocol itself. Usually you don't have to explicitly write the Self. part, but because your generic type has the same name as this one, Swift can't tell them apart otherwise.

The difference is more obvious if you change the name of the generic type:

func accumulate<E>(_ transform: (E) -> E) -> [E] 

This is equivalent to the accumulate<Element> version — changing the name simply highlights what's actually happening.

In a more general sense, Swift will let you name your types whatever you wish. But if a types' name conflicts with another type from a different scope, then you either have to disambiguate it. If you don't disambiguate, Swift will choose the most-local match. In your function, the generic type is "most-local".

Imagine you were to define your own String type:

struct String {   // ... } 

This is totally valid, but if you want to then use the String type provided by the Swift standard lib, you have to disambiguate like this:

let my_string: String = String() let swift_string: Swift.String = "" 

And this is the reason why Andrea changed the signature of the function. You need to tell the compiler which "Element" type you're referring to.

func accumulate<Element>(_ transform: (Self.Element) -> Element) -> [Element] 

In general I would advise against having a generic type match the name of another type you're using. It's just confusing for everyone. 😄

Answers 4

I'm not so sure about your first question. If it works in the playground, but not in your tests, my first guess would be to make the function public. Tests are usually defined in separate modules, and to make something visible in another module, it should be declared public.

extension Collection {   public func accumulate //... } 

Answers 5

When implementing an extension to a Collection, the associated type of the collection would be by default Element; It would be confusing to name your generic as "Element" (func accumulate<Element>), however, for your case, there is even no need to declare your method signature as follows:

func accumulate<Element>(_ transform: (Self.Element) -> Element) -> [Element] 

Instead, it shall be:

func accumulate(_ transform: (Element) -> Element) -> [Element] 

Also, if you are aiming to let your method to be functional only for integers, you should constraint your extension to be applicable only for collections of BinaryInteger, as follows:

extension Collection where Element: BinaryInteger {     func accumulate(_ transform: (Element) -> Element) -> [Element] {          var array: [Element] = []         for element in self {             array.append(transform(element))         }         return array     } } 

Or for expanding the scope, it could be Numeric instead.

Read More

Tuesday, November 14, 2017

Incompatible types inferred type does not conform to equality constraint(s)

Leave a Comment

So I have a model Model.

public class Model { .... }  

This has two subclasses:

public class SubmodelA extend Model { .... } 

and

public class SubmodelB extend Model { .... } 

These three are wrapped under Data class.

public class ApiData<T extends Model> {      public T data;  } 

My general response wrapper looks like this:

public class ApiResponse<DATA> {      DATA data; } 

The "dummy" api operation remains the same:

public interface Endpoints {      Call<ApiResponse<ApiData>> getData(); } 

I have an implementation of retrofit2.Callback to handle the responses:

public class ApiCallbackProxy<T> implements retrofit2.Callback<T> {      public interface ApiResultListener<RESPONSE_TYPE> {         void onResult(RESPONSE_TYPE response, ApiError error);     }      private ApiResultListener<T> mListener;      private ApiCallbackProxy(ApiResultListener<T> listener) {         mListener = listener;     }      @Override     public void onResponse(Call<T> call, Response<T> response) {      }      @Override     public void onFailure(Call<T> call, Throwable t) {      }      public static <T> ApiCallbackProxy<T> with(ApiResultListener<T> callback) {         return new ApiCallbackProxy<>(callback);     } } 

The ApiClient

public class ApiClient {      public Endpoints mRetrofit;      public ApiClient() {        Retrofit retrofit = new Retrofit.Builder().build();        mRetrofit = retrofit.create(Endpoints.class);     }      public <U extends Model> void getData(ApiResultListener<ApiResponse<ApiData<U>>> callback) {        //Compiler hits here        mRetrofit.getData().enqueue(ApiCallbackProxy.with(callback));     } } 

Compiler hits at ApiCallbackProxy.with(callback) with this error:

enter image description here

So I want depending on where this API call is used in the app to return a different subclass of model or the model itself.

ie.

public static void main (String[] args) {     ApiClient apiClient = new ApiClient();     apiClient.getData(listener2); }   public static final ApiResultListener<ApiResponse<Data<SubmodelA>>> listener = (response, error) -> {};  public static final ApiResultListener<ApiResponse<Data<Model>>> listener2 = (response, error) -> {};  public static final ApiResultListener<ApiResponse<Data<SubmodelB>>> listener3 = (response, error) -> {}; 

1 Answers

Answers 1

The ApiClient class has a listener that expects ApiData<U> in the response.

The problem is, there is no U. You have an Endpoint, and the endpoint has no generic types, and it returns just ApiData with no concrete type selected for the generic.

This is a case of generics gone wrong. The usual idea would be to make Endpoint generic:

public interface Endpoints<U> {     Call<ApiResponse<ApiData<U>>> getData(); } 

However, what does the Retrofit do? It turns HTTP API into Java interface. And looking at the most simple example at the github repo of Retrofit, it seems pretty clear to me that you are supposed to put interfaces that access some real HTTP endpoint. It is not some abstract GET.

So you'd rather give it a concrete type than make it generic. Do something like:

public interface Endpoints {     Call<ApiResponse<ApiData<Model>>> getData(); } 

I expect Retrofit to deserialize the data in the response to your Model. So, having a concrete class rather than an unset generic type variable is crucial to the successful deserialization. However, you can only use it with listeners being either of the following:

ApiResultListener<ApiResponse<Data<Model>>> ApiResultListener<ApiResponse<Data<? super Model>>> 

Also, in the older part of the question, the ApiResponse<Payload> part where the generic type variable looks like it was Payload class, now that is quite devious :)

Read More

Tuesday, October 10, 2017

SerializationException: Could not find type 'System.Collections.Generic.List`1 in c# unity3d

Leave a Comment

I am trying to serialize and deserialize an object in c# unity3d. For that I am using the below code. But I am getting an error mentioned below.

Error: SerializationException: Could not find type 'System.Collections.Generic.List`1[[ABC, Assembly-CSharp, Version=1.0.2.18931, Culture=neutral, PublicKeyToken=null]]'.

This is not happening while I serialize the object save to file and load it from file while I am playing the game with out stopping the game.

But the error occurs if I stop the game and change any line of code ( irrelevant to serialization and Deserialization )and load data from file saved previously and trying to deserialize I am getting an SerializationException.

I am using visual studio editor and unity3d version is 5.5.4

I may be missing something very simple thing. could someone help me in resolving this.

Thanks.

public static string SerializeObject<T>(T objectToSerialize) {     BinaryFormatter bf = new BinaryFormatter();     MemoryStream memStr = new MemoryStream();      try     {         bf.Serialize(memStr, objectToSerialize);         memStr.Position = 0;          return Convert.ToBase64String(memStr.ToArray());     }     finally     {         memStr.Close();     } }  public static T DeserializeObject<T>(string str) {     BinaryFormatter bf = new BinaryFormatter();     bf.Binder = new CurrentAssemblyDeserializationBinder();     byte[] b = Convert.FromBase64String(str);     MemoryStream ms = new MemoryStream(b);      try     {         return (T)bf.Deserialize(ms);     }     finally     {         ms.Close();     } } 

Class I am using:

    [Serializable]    public class ABC : ISerializable   {     public SerializableDictionary<int, ExampleClass> a = new SerializableDictionary<int, ExampleClass>();      public GameObject b;     public GameObject c;     public bool d = false;     public ABC e;     public int f;     public string g = "";     public int h = -1;     public int i = -1;     public int j = -1;     public string k = "default";     public XYZ l = XYZ.P;   }      [Serializable]     public enum XYZ     {         P,         Q     }       [Serializable()]     public class ABCListWrapper : ISerializable     {      public List<ABC> abcMappings = new List<ABC>();     public string version = "1.53";     public float interval;     }       //Serilization      abcLW = new ABCListWrapper();     abcW = getABCListWObj();     string abcWString = SerializeObject(abcW);     File.WriteAllText(Application.streamingAssetsPath + "/filename.json", abcWString);       //Deserilization call      ABCListWrapper l = new ABCListWrapper();     string l_1 = File.ReadAllText(Application.streamingAssetsPath + "/filename.json");     l =  DeserializeObject<ABCListWrapper>(l_1); 

Attempt to resolve the issue:

public sealed class CurrentAssemblyDeserializationBinder : SerializationBinder {     public override Type BindToType(string assemblyName, string typeName)     {         Version assemVer1 = Assembly.GetExecutingAssembly().GetName().Version;         Debug.Log("ASSEM VER: " + assemVer1 + "--NAME--" + assemblyName + " --OVERAL-- " + Assembly.GetExecutingAssembly().FullName + " --TYPE-- " + typeName );         //assemblyName = Assembly.GetExecutingAssembly().FullName.Replace(assemVer1.ToString(), "1.0.2.23455");         //string assemblyNameCustom = "Assembly-CSharp, Version=1.0.2.18931, Culture=neutral, PublicKeyToken=null";          bool isList = false;          if (typeName.Contains("List`1"))             isList = true;         // other generics need to go here          if (isList)             return Type.GetType(string.Format("System.Collections.Generic.List`1[[{0}, {1}]]", "ABC", "Assembly-CSharp, Version=1.0.2.18931, Culture=neutral, PublicKeyToken=null"));         else             return Type.GetType(string.Format("{0}, {1}", assemblyName, typeName));      }  } 

But I am getting the same exception and the log in BindToType is never printed. So it means the function BindToType in the SerilizationBinder.

2 Answers

Answers 1

The binary formatter is storing the assembly version information along with the serialized type. So even when the type is not changed, the serialization/deserialization changes as soon as the assembly is updated.

See this related Q/A for details: Binary Deserialization with different assembly version and the relevant MSDN article.

Normally I would close-vote this as a duplicate, but I can't because of the open bounty, so I decided to answer instead ;)

Answers 2

For fast binary serialization Protocol Buffers can be good option. Also it should resolve compatibility issues (you can control fields order/exclusion manually)

Read More

Monday, April 24, 2017

Scala: generic weighted average function

Leave a Comment

I want to implement a generic weighted average function which relaxes the requirement on the values and the weights being of the same type. ie, I want to support sequences of say: (value:Float,weight:Int) and (value:Int,weight:Float) arguments and not just: (value:Int,weight:Int). [See my earlier question in the run up to this.]

This is what I currently have:

def weightedSum[A: Numeric](weightedValues: GenSeq[(A, A)]): (A, A)  def weightedAverage[A: Numeric](weightedValues: GenSeq[(A, A)]): A = {     val (weightSum, weightedValueSum) = weightedSum(weightedValues)     implicitly[Numeric[A]] match {         case num: Fractional[A] => ...         case num: Integral[A] => ...         case _ => sys.error("Undivisable numeric!")     } } 

This works perfectly if I feed it for example:

val values:Seq[(Float,Float)] = List((1,2f),(1,3f)) val avg= weightedAverage(values) 

However if I don't "upcast" the weights from Int to Float:

val values= List((1,2f),(1,3f)) //scalac sees it as Seq[(Int,Float)]  val avg= weightedAverage(values) 

Scala compiler will tell me:

error: could not find implicit value for evidence parameter of type Numeric[AnyVal]
val avg= weightedAverage(values)

Is there a way of getting round this?

I had an attempt at writing a NumericCombine class that I parameterized with A and B which "combines" the types into a "common" type AB (for example, combining Float and Int gives you Float) :

abstract class NumericCombine[A: Numeric, B: Numeric] {     type AB <: AnyVal      def fromA(x: A): AB     def fromB(y: B): AB     val num: Numeric[AB]      def plus(x: A, y: B): AB = num.plus(fromA(x), fromB(y))     def minus(x: A, y: B): AB = num.minus(fromA(x), fromB(y))     def times(x: A, y: B): AB = num.times(fromA(x), fromB(y)) } 

and I managed to write simple times and plus functions based on this with the typeclass pattern, but since NumericCombine introduces a path-dependent type AB, "composing" the types is proving to be more difficult than I expected. look at this question for more information and see here for the full implementation of NumericCombine.

Update

A somewhat satisfactory solution has been obtained as an answer to another question (full working demo here) however there is still room for some design improvement taking into account the points raised in the discussion with @ziggystar.

2 Answers

Answers 1

Linear combinations

I think the more general task that involves weighting/scaling some elements of type T by a scalar of type S is that of a linear combination. Here are the constraints on the weights for some tasks:

So the most general case according to this classification is the linear combination. According to Wikipedia, it requires the weights, S, to be a field, and T to form a vector space over S.

Spire

You could set up these requirements with typeclasses. There's also spire, which already has typeclasses for Field and VectorSpace. I have never used it myself, so you have to check it out yourself.

Float/Int won't work

What is also apparent from this discussion, and what you have already observed, is the fact that having Float as a weight, and Int as the element type will not work out, as the whole numbers do not form a vector space over the reals. You'd have to promote Int to Float first.

Solution via typeclass

There are only two major candidates for the scalar type, i.e., Float and Double. And mainly only Int is a candidate for promoting, so you could do the following as a simple and not so general solution:

case class Promotable[R,T](promote: R => T)  object Promotable {   implicit val intToFloat = Promotable[Int,Float](_.toFloat)   implicit val floatToDouble = Promotable[Float,Double](_.toDouble)   implicit val intToDouble = Promotable[Int,Double](_.toDouble)    implicit def identityInst[A] = Promotable[A,A](identity) }As a "small" solution you could write a typeclass   def weightedAverage[S,VS](values: Seq[(S,VS)])(implicit p: Promotable[VS,S]) = ??? 

Answers 2

First of all your template is wrong. (And sorry if the "template" expression is wrong - I am a novice in scala). Your functions expect tuples where both elements are of the same type ( [A: Numeric] ) , instead of tuples where elements are of different types ( [A: Numeric, B: Numeric] ) ( (Int, Float) vs (Float, Float) )

Anyway the below compiles and hopefully will work well after you fill it with your desired calculus.

import scala.collection._  def weightedSum[A: Numeric, B: Numeric](weightedValues: GenSeq[(A,B)]): (A,B) = {   weightedValues.foldLeft((implicitly[Numeric[A]].zero, implicitly[Numeric[B]].zero)) { (z, t) =>     (   implicitly[Numeric[A]].plus(z._1, t._1),          implicitly[Numeric[B]].plus(z._2, t._2)     )    }  }  def weightedAverage[A: Numeric, B: Numeric](weightedValues: GenSeq[(A,B)]): A = {   val (weightSum, weightedValueSum) = weightedSum(weightedValues)   implicitly[Numeric[A]] match {     case num: Fractional[A] => implicitly[Numeric[A]].zero     case num: Integral[A] => implicitly[Numeric[A]].zero     case _ => sys.error("Undivisable numeric!")   } }  val values1: Seq[(Float, Float)] = List((1, 2f), (1, 3f)) val values2: Seq[(Int, Float)] = List((1, 2f), (1, 3f))  val wa1 = weightedAverage(values1) val wa2 = weightedAverage(values2) 
Read More

Thursday, March 23, 2017

Call method on subclass to UITableViewCell with generic parameter value based on protocol or base class

Leave a Comment

I want to simplify the calling of a "setup"-method in UITableViewCell subclasses. However, not all setup methods are the same, but their parameters inherit from the same type. Is it possible with generics or protocol to not have to cast the parameter every time?

First I a cellForRow-method like this:

class DataSource<V : UIViewController, T: TableViewCellData, VM: ViewModel> : NSObject, UITableViewDataSource, UITableViewDelegate {      var dataCollection: TableViewDataCollection<T>!     var viewModel: VM!      func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {         let cellData = dataCollection.object(for: indexPath)         let cell = tableView.dequeueReusableCell(withIdentifier: cellData.identifier(), for: indexPath)         if let setupableCell = cell as? CellDataSetupable {             setupableCell.setup(with: cellData, viewModel: viewModel)         }         return cell     } }  protocol CellDataSetupable : class {     func setup(with cellData: TableViewCellData, viewModel: ViewModel) } 

where I setup the cell with cellData and viewModel.

In my (many) custom UITableViewCell subclasses:

extension BlurbTableViewCell : CellDataSetupable {     func setup(with cellData: TableViewCellData, viewModel: ViewModel) {         guard let cellData = cellData as? HomeViewTableViewCellData else { return }         guard let viewModel = viewModel as? HomeViewModel else { return }          // Use cellData and viewModel to setup cell appearance      } } 

where HomeViewTableViewCellData is subclass of TableViewCellData and HomeViewModel is subclass of ViewModel

Instead I want to remove the guards and directly write something like this:

extension BlurbTableViewCell : CellDataSetupable< {     func setup(with cellData: HomeViewTableViewCellData, viewModel: HomeViewModel) {            // Use cellData and viewModel to setup cell appearance      } } 

Attempted solutions (that does not work):

Any ideas or do I have to live with my castings?

Edit 1: After suggestions from Nate Mann below I tried this code (note that I have renamed some generic types):

// This works fine extension TransactionTableViewCell : CellDataSetupable {     typealias CellData = HomeViewTableViewCellData     typealias VM = HomeViewModel     func setup(with cellData: CellData, viewModel: VM) {         //Setup cell appearance ...     } } 

This row also works fine: (note the extra where clause)

class DataSource<VC : UIViewController, TVCD: TableViewCellData, VM: ViewModel, CDS: CellDataSetupable> : NSObject, UITableViewDataSource, UITableViewDelegate where CDS.TVCD == TVCD, CDS.VM == VM {     // ...      func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {         let cellData = dataCollection.object(for: indexPath)         let cell = tableView.dequeueReusableCell(withIdentifier: cellData.identifier(), for: indexPath)         if let setupableCell = cell as? CDS {             setupableCell.setup(with: cellData, viewModel: viewModel)         }         return cell     } 

But changing from

class HomeTableViewDataSource: DataSource<HomeViewController, HomeViewTableViewCellData, HomeViewModel> { 

to

class HomeTableViewDataSource: DataSource<HomeViewController, HomeViewTableViewCellData, HomeViewModel, CellDataSetupable> { 

give this error:

Using 'CellDataSetupable' as a concrete type confirming to protocol 'CellDataSetupable' is not supported 

Edit 2: Using a concrete version of a generic baseclass for a UITableViewCell class is not either possible. See Why can't interface builder use a concrete generic subclass of of UIView?

3 Answers

Answers 1

I think this should work:

class DataSource<V : UIViewController, T: TableViewCellData, VM: ViewModel, X: CellDataSetupable> : NSObject where X.M == VM, X.T == T {      var dataCollection: TableViewDataCollection!     var viewModel: VM!      func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {         let cellData = dataCollection.object(for: indexPath) as! T         let cell = tableView.dequeueReusableCell(withIdentifier: cellData.identifier(), for: indexPath)         if let setupableCell = cell as? X {             setupableCell.setup(with: cellData, viewModel: viewModel)         }         return cell     }  }   protocol CellDataSetupable: class {     associatedtype T: TableViewCellData     associatedtype M: ViewModel     func setup(with cellData: T, viewModel: M) }   class BlurbTableViewCell: UITableViewCell, CellDataSetupable {     func setup(with cellData: HomeViewTableViewCellData, viewModel: HomeViewModel) {          // Use cellData and viewModel to setup cell appearance     }  } 

Answers 2

When you are using DataSource, you provide concrete types that the DataSource works with. So,

class HomeTableViewDataSource: DataSource<HomeViewController, HomeViewTableViewCellData, HomeViewModel, CellDataSetupable> { 

should really be

class HomeTableViewDataSource: DataSource<HomeViewController, HomeViewTableViewCellData, HomeViewModel, HomeTableViewCell> { 

where HomeTableViewCell is a concrete UITableViewCell subclass that conforms to CellDataSetupable (like BlurbTableViewCell or TransactionTableViewCell). It will work fine then.

Here is a simple generic TableViewDataSource example that works and perhaps is a little easier to understand.

Generic types:

import UIKit  protocol CellDataProtocol {     var cellIdentifier: String { get } }  protocol ConfigurableCell {     associatedtype Data: CellDataProtocol     func configure(with data: Data) }  class DataSource<CellData: CellDataProtocol, Cell: ConfigurableCell>: NSObject, UITableViewDataSource where Cell.Data == CellData {      var data: [CellData]!      func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {         return data.count     }      func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {         let cellData = data[indexPath.row]         let cell = tableView.dequeueReusableCell(withIdentifier: cellData.cellIdentifier, for: indexPath)         if let cell = cell as? Cell {             cell.configure(with: cellData)         }         return cell     } } 

Concrete classes that are built on top of the code above:

class DataObject: CellDataProtocol {     var cellIdentifier: String {         return "Identifier"     }      // an additional property of the class     var number: Int {         return 5     } }  class TableViewCell: UITableViewCell, ConfigurableCell {     func configure(with data: DataObject) {         // configure cell UI with data          // properties can be used here         // since the exact type is known         self.textLabel?.text = "\(data.number)"     } }  let dataSource = DataSource<DataObject, TableViewCell>()  class ConcreteDataSource: DataSource<DataObject, TableViewCell> {     // additional functionality } 

Edit: you subclass can also work with different types of cells if you want.

class SubDataSource<Cell: ConfigurableCell>: DataSource<DataObject, Cell> where Cell.Data == DataObject {     // additional functionality }  let d = SubDataSource<TableViewCell>() 

Hope this helps! Good luck!

Answers 3

My own idea of the answer is that it's not possible at the moment.

Nate Mann's answer requires me to specify a concrete implementation of CellDataSetupable which I do not want.

timaktimak's answers either needs a concrete implementation as well or requires subclassing of a UIView.

Read More

Thursday, April 7, 2016

Implementing multiparameter C++ template like behaviour on C# using Policy Pattern

Leave a Comment

I'm trying to implement a c++ like template with C# generics and policy pattern based on this answer

This is a sample of the pattern:

interface ISomePolicy<T,U> {     void _doSomething(U u); }   class MyClass<T,U>:      ISomePolicy<int, double>,      ISomePolicy<int, int>     {      internal T myElement {get;set;}      public MyClass(T Element) {         myElement = Element;     }      void ISomePolicy<int, double>._doSomething(double u)     {         Console.WriteLine("this is int, double");     }      void ISomePolicy<int, int>._doSomething(int u)     {         Console.WriteLine("this is int, int");     }      }  static class MyClassExtension {      //What I want to do     public static void doSomething<P, T, U>(this P oTh, U u) where P : MyClass<T, U>, ISomePolicy<T, U>     {         oTh._doSomething(u);     }  } 

My intended behaviour is like this:

  MyClass<int, double> oClass = new MyClass<int, double>(3);    oClass.doSomething(0.5); //This works   oClass.doSomething(1);   //This works    oClass.doSomething("This should fail"); //Breaks at compile time               MyClass<string, double> oClass1 = new MyClass<string, double>("sadfsd"); //Not implemented, wasn't able to prevent the construction.    oClass1.doSomething(0.4); //Breaks at compile time 

But so far I wasn't able to make .net accept Generic Extension with less arguments than parameters

I can call the interface explicitly, which is horrible verbose defeating the purpose of all this.

oClass.doSomething < MyClass<int, double>,int,double>(0.5); 

I thought of working that around with a wrapper:

static class MyClassExtension{     private static void wrappedDoSomething<P, T, U>(this P oTh, U u)      where P : MyClass<T, U>, ISomePolicy<T, U>     {         oTh._doSomething(u);     }      public static void doSomething<T, U>(this MyClass<T, U> oTh, U u)      {         oTh.wrappedDoSomething<MyClass<T, U>, T, U>(u);     } } 

But the wrapper can't resolve both types for the wrapped function, failing with:

Error 1 The type 'MyClass' cannot be used as type parameter 'P' in the generic type or method 'MyClassExtension.wrappedDoSomething(P, U)'. There is no implicit reference conversion from 'MyClass' to 'ISomePolicy'

Any insights to fix the parameters issue or redesign all this are appreciated.


For context this would be used to wrap I/O translators. T in my case would be the target I/O format, and U the object representation of that data used by my framework.

I'm aware that this can be easily achieved with delegates or interfaces, but the objective is that the framework user easily instantiates the desired translation, and if an implementation doesn't exists, it can be trivially added to a common interface.


EDIT: Resolving a generic method from inside another generic method/class neither seems to work on mono.

2 Answers

Answers 1

Usually, policies should not contain data. For example,

interface ISomePolicy<T, U> {     void _doSomething(T t, U u); }  struct SomePolicyImplementation :     ISomePolicy<int, double>,     ISomePolicy<int, int>,     ISomePolicy<double, double> {     void ISomePolicy<int, int>._doSomething(int t, int u)         => Console.WriteLine("this is int, int");      void ISomePolicy<int, double>._doSomething(int t, double u)         => Console.WriteLine("this is int, double");      void ISomePolicy<double, double>._doSomething(double t, double u)         => Console.WriteLine("this is double, double"); }  static class SomePolicyExtension {     public static void doSomething<P, T, U>(this P policy, T t, U u)         where P : struct, ISomePolicy<T, U>         => policy._doSomething(t, u); } 

If you would like to combine policies and data then you may consider different interface

interface IEmbeddedPolicy<U> {     void _doSomething(U u); }  class MyClass<T> :     IEmbeddedPolicy<double>,     IEmbeddedPolicy<int> {     public T Value { get; }      public MyClass(T value) { this.Value = value; }      void IEmbeddedPolicy<int>._doSomething(int u)         => Console.WriteLine("this is T, int");      void IEmbeddedPolicy<double>._doSomething(double u)         => Console.WriteLine("this is T, double"); }  static class EmbeddedPolicyExtension {     public static void doSomething<E, U>(this E embedded, U u)         where E : IEmbeddedPolicy<U>         => embedded._doSomething(u); } 

Or combination of these two concepts

class MySuperClass<P, T>:     IEmbeddedPolicy<double>,     IEmbeddedPolicy<int>     where P: struct, ISomePolicy<T, double>, ISomePolicy<T, int> {     public T Value { get; }      public MySuperClass(T value) { this.Value = value; }      void IEmbeddedPolicy<int>._doSomething(int u)         => new P()._doSomething(this.Value, u);      void IEmbeddedPolicy<double>._doSomething(double u)         => new P()._doSomething(this.Value, u); } 

Usage:

// independent policy var policy = new SomePolicyImplementation();  policy.doSomething(5, 6); policy.doSomething(5, 6.7); policy.doSomething(5.3, 6.7);  // embedded policy var my = new MyClass<int>(54); my.doSomething(5); my.doSomething(89.7);  // combination var x = new MySuperClass<SomePolicyImplementation, int>(53); x.doSomething(9); x.doSomething(18.3); 

Answers 2

Tried your code, but even simple calls did not work out of box. Main problem is that MyClass contains unknown element type 'myEement' - that type cannot be deduced from function call parameters. However - if you make a generalization and omit object type - your sample will work in out of box manner:

using System; using System.Collections.Generic;  interface ISomePolicy<U>  {     void _doSomething(U u); }  public class MyClass<U> :      ISomePolicy<double>,      ISomePolicy<int> {     internal object myEement { get; set; }      public MyClass(object Element)     {         myEement = Element;     }      void ISomePolicy<double>._doSomething(double u)     {         Console.WriteLine("this is double");     }      void ISomePolicy<int>._doSomething(int u)     {         Console.WriteLine("this is int");     } }  static class MyClassExtension {     public static void doSomething<P, U>(this P oTh, U u) where P : ISomePolicy<U>     {         oTh._doSomething(u);     } }  class Program {     static void Main()     {         MyClass<double> oClass = new MyClass<double>(3);         oClass.doSomething(0.5); //This works         oClass.doSomething(1);   //This works                     //oClass.doSomething("Will not work");     } } 

What is up to myEement (or you probably meant myElement) - you can get's it's type at run-time if necessary.

myElement.GetType(), or cast to it - e.g. if( myElement is int ) DoSomethingWithInt( (int) myElement ); 

However - reflection always might slow down your execution. If you don't intend to create super heavy class hierarchy with huge amount of instances - then this should be sufficient for your needs.

Read More