none
Deserialising StorageFile into List ofInterfaces

    Question

  • I have a List<IMyItem> which I serialise into a StorageFile and save to my Roaming storage.

    My problem comes when I come to deserialise it back into a List<IMyItem>, I get the ubiquitous error:

    Could not create an instance of type IMyItem. Type is an interface or abstract class and cannot be instantiated.

    I am using NewtonSoft for serialisation. How can I do this?

    Wednesday, April 19, 2017 9:46 AM

All replies

  • Hello,

    You should have a class that implements that interface and deserialize to the class.

    See this example

    http://stackoverflow.com/questions/28012335/json-net-deserializeobject-to-list-of-objects


    Please remember to mark the replies as answers if they help and unmark them if they provide no help, this will help others who are looking for solutions to the same or similar problem. Contact via my Twitter (Karen Payne) or Facebook (Karen Payne) via my MSDN profile but will not answer coding question on either.
    VB Forums - moderator
    profile for Karen Payne on Stack Exchange, a network of free, community-driven Q&A sites

    Wednesday, April 19, 2017 12:30 PM
    Moderator
  • Hi Karen,

    My issue is that my model is interface driven

    Wednesday, April 19, 2017 12:31 PM
  • Still can work, we use a model based approach e.g. Controller, Model, DTO (in tangent with AutoMapper), Repository were each entity is driven off a Interface.

    Granted we use Web API setup to do de-serialization for us rather than JSON.NET but the same should apply for working with JSON.NET.


    Please remember to mark the replies as answers if they help and unmark them if they provide no help, this will help others who are looking for solutions to the same or similar problem. Contact via my Twitter (Karen Payne) or Facebook (Karen Payne) via my MSDN profile but will not answer coding question on either.
    VB Forums - moderator
    profile for Karen Payne on Stack Exchange, a network of free, community-driven Q&A sites

    Wednesday, April 19, 2017 2:19 PM
    Moderator
  • Hi Craig Muckleston(MCPD, MCTS),

    Thank you for posting here.

    For the use of NewtonSoft for serialisation, please refer to the link.

    Could you provide more information about your question? Some demo code for us to test?

    Here is a thread for reference. JSON.NET - how to deserialize collection of interface-instances?

    Best Regards,

    Wendy


    MSDN Community Support
    Please remember to click "Mark as Answer" the responses that resolved your issue, and to click "Unmark as Answer" if not. This can be beneficial to other community members reading this thread. If you have any compliments or complaints to MSDN Support, feel free to contact MSDNFSF@microsoft.com.

    Thursday, April 20, 2017 7:38 AM
    Moderator
  • Here is a quick example:

    using Newtonsoft.Json;
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;
    namespace ConsoleApplication1
    {
        interface IMyItem
        {
            string Name { get; set; }
        }
        class MyItem : IMyItem
        {
            private string _name;
            public string Name
            {
                get { return _name; }
                set { _name = value; }
            }
        }
        class Program
        {
            static List<IMyItem> myItems = new List<IMyItem>();
            static void Main(string[] args)
            {
                myItems.Add(new MyItem() { Name = "Andrew" });
                myItems.Add(new MyItem() { Name = "Bob" });
                myItems.Add(new MyItem() { Name = "Craig" });
                var serialised = JsonConvert.SerializeObject(myItems);
                try
                {
                    var deserialised = JsonConvert.DeserializeObject<List<IMyItem>>(serialised); //boom!
                }
                catch (Exception ex)
                {
                    Console.WriteLine(ex.Message);
                }
                Console.Read();
            }
        }
    }

    Thursday, April 20, 2017 8:31 AM
  • Hi Craig,

    One far-fetched solution would be to deserialize each of the serialized IMyItem into a JObject. Then, pass the JObject to a class inheriting from System.Runtime.Remoting.Proxies.RealProxy. That class should then override the    RealProxy.Invoke(IMessage message)with the adequate code and voila!

    Following comes the example of a mockup of an interface instantiation that I had created some years ago.

    I hope this helps,

    Chad

        public interface IPolymorphable
            : IIdentifiable
        {
    
            DynamicDictionary Properties { get; }
    
        }
    
    /// <summary>
        /// Acts a <see cref="RealProxy"/> for an <see cref="IPolymorphable"/>
        /// </summary>
        /// <typeparam name="TInterface">The root interface type of the interface hierarchy chain the <see cref="Polymorph{TInterface}"/> can be casted to</typeparam>
        internal sealed class PolymorphProxy<TInterface>
            : RealProxy
            where TInterface : IPolymorphable
        {
    
            /// <summary>
            /// Initializes a new <see cref="PolymorphProxy<TInterface>"/>
            /// </summary>
            /// <param name="polymorph">The <see cref="IPolymorphable"/> for which to create the <see cref="PolymorphProxy{TInterface}"/></param>
            internal PolymorphProxy(IPolymorphable polymorph)
                : base(typeof(TInterface))
            {
                this.Polymorph = polymorph;
            }
    
            /// <summary>
            /// Gets the <see cref="IPolymorphable"/> the <see cref="PolymorphProxy{TInterface}"/> proxies
            /// </summary>
            internal IPolymorphable Polymorph { get; private set; }
    
            /// <summary>
            /// Processes the specified <see cref="IMethodCallMessage"/>
            /// </summary>
            /// <param name="message">The <see cref="IMethodCallMessage"/> to process</param>
            /// <returns>A new <see cref="ReturnMessage"/> wrapping the called method's return</returns>
            public override IMessage Invoke(IMessage message)
            {
                IMethodCallMessage methodCall;
                object methodResult;
                string propertyName;
                ReturnMessage methodReturn;
                methodCall = (IMethodCallMessage)message;
                //Check whether the called method is a GET or a SET accessor
                if (this.IsPropertyGetAccessorMethod(methodCall.MethodName, out propertyName))
                {
                    //If the Polymorph's properties dictionary cannot get the value specified by the methodCall's name, return a missing member exception
                    if (!this.Polymorph.Properties.TryGetValue(propertyName, out methodResult))
                    {
                        methodReturn = new ReturnMessage(new MissingMemberException("Failed to retrieve the specified property '" + propertyName + "' value from the proxied message's properties dictionary"), methodCall);
                        return methodReturn;
                    }
                    //Returns the value found in the ProxiedMessage's properties dictionary
                    methodResult = this.Polymorph.Properties[propertyName];
                    methodReturn = new ReturnMessage(methodResult, methodCall.InArgs, methodCall.InArgCount, methodCall.LogicalCallContext, methodCall);
                    return methodReturn;
                }
                else
                {
                    if (this.Polymorph.Properties.ContainsKey(propertyName))
                    {
                        this.Polymorph.Properties[propertyName] = methodCall.Args[0];
                    }
                    else
                    {
                        this.Polymorph.Properties.Add(propertyName, methodCall.Args[0]);
                    }
                    methodReturn = new ReturnMessage(null, methodCall.InArgs, methodCall.InArgCount, methodCall.LogicalCallContext, methodCall);
                    return methodReturn;
                }
            }
    
            /// <summary>
            /// Gets a boolean indicating whether or not the specified method name is a property get accessor
            /// </summary>
            /// <param name="methodName">The method name to check</param>
            /// <param name="propertyName">The name of the property accessed by the method which's name has been supplied</param>
            /// <returns>A boolean indicating whether or not the specified method name is a property get accessor</returns>
            internal bool IsPropertyGetAccessorMethod(string methodName, out string propertyName)
            {
                if (methodName.StartsWith("get_"))
                {
                    propertyName = methodName.Substring("get_".Length);
                    return true;
                }
                else if (methodName.StartsWith("set_"))
                {
                    propertyName = methodName.Substring("set_".Length);
                    return false;
                }
                else
                {
                    throw new ArgumentException("The specified methodName '" + methodName + "' is not a valid property accessor method name");
                }
            }
    
            /// <summary>
            /// Gets the <see cref="PolymorphProxy{TInterface}"/>'s transparent proxy
            /// </summary>
            /// <returns>The <see cref="PolymorphProxy{TInterface}"/>'s transparent proxy</returns>
            internal new TInterface GetTransparentProxy()
            {
                return (TInterface)base.GetTransparentProxy();
            }
    
        }
    
    /// <summary>
        /// Represents a dynamic collection of <see cref="string"/> keys and <see cref="object"/> values.<para></para>
        /// This collection is serialization-friendly, as all <see cref="KeyValuePair{TKey, TValue}"/> are stored into an underlying list of <see cref="DynamicData"/><para></para>
        /// Note that adding non-serializable values to the dictionary will provoke an exception
        /// </summary>
        [Serializable, DataContract]
        [KnownType(typeof(DynamicData))]
        public class DynamicDictionary
            : DynamicObject, IDynamicDictionary
        {
    
            /// <summary>
            /// Initializes a new instance of the <see cref="DynamicDictionary"/> class
            /// </summary>
            public DynamicDictionary()
            {
                this._Values = new List<DynamicData>();
                this._Dictionary = new Dictionary<string, object>();
            }
    
            /// <summary>
            /// Initializes a new instance of the <see cref="DynamicDictionary"/> class
            /// </summary>
            public DynamicDictionary(IDictionary<string, object> values)
            {
                this._Values = new List<DynamicData>();
                this._Dictionary = values;
                foreach(KeyValuePair<string, object> kvp in this._Dictionary)
                {
                    this._Values.Add(new DynamicData(kvp.Key, kvp.Value));
                }
            }
    
            /// <summary>
            /// Gets the underlying list of <see cref="DynamicData"/> ensuring the serialization of the dictionary's keys and values
            /// </summary>
            [DataMember]
            private List<DynamicData> _Values;
    
            /// <summary>
            /// Gets the underlying <see cref="IDictionary{string, object}"/>
            /// </summary>
            private IDictionary<string, object> _Dictionary;
    
            /// <summary>
            /// Gets the collection of the dictionary's keys
            /// </summary>
            public ICollection<string> Keys
            {
                get
                {
                    return this._Dictionary.Keys;
                }
            }
    
            /// <summary>
            /// Gets the collection of the dictionary's values
            /// </summary>
            public ICollection<object> Values
            {
                get
                {
                    return this._Dictionary.Values;
                }
            }
    
            /// <summary>
            /// Gets an integer representing the dictionary's element count
            /// </summary>
            public int Count
            {
                get
                {
                    return this._Dictionary.Count;
                }
            }
    
            /// <summary>
            /// Gets a boolean indicating whether or not the dictionary is read-only
            /// </summary>
            public bool IsReadOnly
            {
                get
                {
                    return false;
                }
            }
    
            /// <summary>
            /// Get the value associated with the specified key
            /// </summary>
            /// <param name="key">A <see cref="string"/> representing the key of the value to get</param>
            /// <returns></returns>
            public object this[string key]
            {
                get
                {
                    return this._Dictionary[key];
                }
    
                set
                {
                    this._Dictionary[key] = value;
                }
            }
    
            /// <summary>
            /// Converts the <see cref="DynamicDictionary"/> a new <see cref="IDictionary{TKey, TValue}"/> instance
            /// </summary>
            /// <returns>A new <see cref="IDictionary{TKey, TValue}"/> instance based on the <see cref="IDynamicDictionary"/></returns>
            public IDictionary<string, object> AsDictionary
            {
                get
                {
                    return this._Dictionary;
                }
            }
    
            /// <summary>
            /// Gets an <see cref="IEnumerable{string}"/> representing the names of the dictionary's dynamic members<para></para>
            /// This method is inherited from the <see cref="DynamicObject"/> type
            /// </summary>
            /// <returns>A <see cref="IEnumerable{string}"/> containing the names of the dictionary's dynamic members</returns>
            public override IEnumerable<string> GetDynamicMemberNames()
            {
                List<string> memberNames;
                memberNames = base.GetDynamicMemberNames().ToList();
                memberNames.AddRange(this._Dictionary.Keys);
                return memberNames;
            }
    
            /// <summary>
            /// Attempts to retrieve the value returned by the specified member<para></para>
            /// This method is inherited from the <see cref="DynamicObject"/> type
            /// </summary>
            /// <param name="binder">The <see cref="GetMemberBinder"/> indicating the member to retrieve the value from</param>
            /// <param name="result">The value contained</param>
            /// <returns>A <see cref="boolean"/> indicating whether or not the specified member has been found</returns>
            public override bool TryGetMember(GetMemberBinder binder, out object result)
            {
                if(base.TryGetMember(binder, out result))
                {
                    return true;
                }
                if(!this._Dictionary.Keys.Contains(binder.Name))
                {
                    return false;
                }
                result = this._Dictionary[binder.Name];
                return true;
            }
    
            /// <summary>
            /// Attempts to set the value of the specified member<para></para>
            /// This method is inherited from the <see cref="DynamicObject"/> type
            /// </summary>
            /// <param name="binder">The <see cref="SetMemberBinder"/> indicating the member to set the value of</param>
            /// <param name="value">The value to set the specified member to</param>
            /// <returns>A <see cref="bool"/> indicating whether or not the operation was successfull</returns>
            public override bool TrySetMember(SetMemberBinder binder, object value)
            {
                if (base.TrySetMember(binder, value))
                {
                    return true;
                }
                if (!this._Dictionary.Keys.Contains(binder.Name))
                {
                    this.Add(binder.Name, value);
                }
                else
                {
                    this._Dictionary[binder.Name] = value;
                    this._Values.FirstOrDefault(d => d.Name.ToLower() == binder.Name.ToLower()).Value = value;
                }
                return true;
            }
    
            /// <summary>
            /// Determines whether or not the dictionary contains the specified key
            /// </summary>
            /// <param name="key">A <see cref="string"/> representing the key to check for</param>
            /// <returns>A <see cref="bool"/> indicating whether or not the key exists</returns>
            public bool ContainsKey(string key)
            {
                return this._Dictionary.ContainsKey(key);
            }
    
            /// <summary>
            /// Adds a value associated with the specified key into the dictionary
            /// </summary>
            /// <param name="key">A <see cref="string"/> representing the key associated with the specified value</param>
            /// <param name="value">The value to add at the specified key</param>
            public void Add(string key, object value)
            {
                this._Dictionary.Add(key, value);
                this._Values.Add(new DynamicData(key, value));
            }
    
            /// <summary>
            /// Removes the specified key - and the value associated with it - from the <see cref="DynamicDictionary"/> and returns a boolean indicating whether or not the operation was successfull
            /// </summary>
            /// <param name="key">A string representing the key of the data to remove</param>
            /// <returns>A boolean indicating whether or not the operation was successfull</returns>
            public bool Remove(string key)
            {
                if (!this._Dictionary.Remove(key))
                {
                    return false;
                }
                this._Values.Remove(this._Values.First(d => d.Name.ToLower() == key.ToLower()));
                return true;
            }
    
            /// <summary>
            /// Attempt to get the value located at the specified key
            /// </summary>
            /// <param name="key">A <see cref="string"/> representing the key of the value to retrieve</param>
            /// <param name="value">The object to assign the retrieved value to, if any</param>
            /// <returns>A boolean indicating whether or not the specified key exists</returns>
            public bool TryGetValue(string key, out object value)
            {
                return this._Dictionary.TryGetValue(key, out value);
            }
    
            /// <summary>
            /// Adds a new entry to the dictionary
            /// </summary>
            /// <param name="item">The entry to add</param>
            public void Add(KeyValuePair<string, object> item)
            {
                this._Dictionary.Add(item.Key, item.Value);
                this._Values.Add(new DynamicData(item.Key, item.Value));
            }
    
            /// <summary>
            /// Clears the dictionary of both all its keys and values
            /// </summary>
            public void Clear()
            {
                this._Dictionary.Clear();
                this._Values.Clear();
            }
    
            /// <summary>
            /// Determines whether or not the dictionary contains the specified item
            /// </summary>
            /// <param name="item">The item to check for</param>
            /// <returns>A <see cref="bool"/> indicating whether or not the dictionary contains the specified item</returns>
            public bool Contains(KeyValuePair<string, object> item)
            {
                return this._Dictionary.Contains(item);
            }
    
            /// <summary>
            /// Copies the dictionary's keys and values into the specified array, starting at the specified array index
            /// </summary>
            /// <param name="array">The array to copy the dictionary contents to</param>
            /// <param name="arrayIndex">The index in the specified array at which to start copying the dictionary's content</param>
            public void CopyTo(KeyValuePair<string, object>[] array, int arrayIndex)
            {
                throw new NotImplementedException();
            }
    
            /// <summary>
            /// Removes the specified item from the dictionary
            /// </summary>
            /// <param name="item">The item to remove</param>
            /// <returns>A boolean indicating whether or not the dictionary could remove the specified item. If false is returned, the specified item does not exist in the dictionary</returns>
            public bool Remove(KeyValuePair<string, object> item)
            {
                if (!this._Dictionary.Remove(item.Key))
                {
                    return false;
                }
                this._Values.Remove(this._Values.First(d => d.Name.ToLower() == item.Key.ToLower()));
                return true;
            }
    
            /// <summary>
            /// Gets the dictionary's <see cref="IEnumerator{KeyValuePair{string, object}}"/>
            /// </summary>
            /// <returns>The dictionary's <see cref="IEnumerator{KeyValuePair{string, object}}"/></returns>
            public IEnumerator<KeyValuePair<string, object>> GetEnumerator()
            {
                return this._Dictionary.GetEnumerator();
            }
    
            /// <summary>
            /// Gets the dictionary's <see cref="IEnumerator{KeyValuePair{string, object}}"/>
            /// </summary>
            /// <returns>The dictionary's <see cref="IEnumerator{KeyValuePair{string, object}}"/></returns>
            IEnumerator IEnumerable.GetEnumerator()
            {
                return this.GetEnumerator();
            }
    
            /// <summary>
            /// Returns an array of all the values contained by the dictionary
            /// </summary>
            /// <returns>An array of objects representing the dictionary's values</returns>
            public object[] ToArray()
            {
                object[] array;
                array = this._Dictionary.Values.ToArray();
                return array;
            }
    
            /// <summary>
            /// Fired upon serialization, this method ensures the copy of all the dictionary's keys and values into a list of <see cref="DynamicData"/> in order to ensure the correct serialization of the dictionary's keys and values
            /// </summary>
            /// <param name="context">The current <see cref="StreamingContext"/></param>
            [OnSerializing]
            private void OnSerializing(StreamingContext context)
            {
                DynamicData data;
                foreach(KeyValuePair<string, object> element in this._Dictionary)
                {
                    data = this._Values.FirstOrDefault(d => d.Name.ToLower() == element.Key.ToLower());
                    if(data == null)
                    {
                        this._Values.Add(new DynamicData(element.Key, element.Value));
                        continue;
                    }
                    if(data.Value != element.Value)
                    {
                        data.Value = element.Value;
                    }
                }
            }
    
            /// <summary>
            /// Fired upon serialization, this method allows the dictionary's keys and values to be restored by deserializing the local list of <see cref="DynamicData"/>
            /// </summary>
            /// <param name="context">The current <see cref="StreamingContext"/></param>
            [OnDeserialized]
            private void OnDeserialized(StreamingContext context)
            {
                this._Dictionary = new Dictionary<string, object>();
                foreach(DynamicData data in this._Values)
                {
                    this._Dictionary.Add(data.Name, data.Value);
                }
            }
    
        }

    Friday, April 21, 2017 4:48 PM