0

I have a problem, here is my code snippet

        using System;
        using System.IO;
        using CsvHelper;
        using System.Xml;
        using System.Linq;
        using System.Xml.Linq;
        using Newtonsoft.Json;
        using System.Collections;
        using System.Globalization;
        using CsvHelper.Configuration;
        using System.Collections.Generic;
        using System.Runtime.InteropServices;

        namespace MXPSQL.EDict{
            public class CvsStuff{
                public CsvConfiguration cvscfg = new CsvConfiguration(CultureInfo.InvariantCulture)
                {
                    NewLine = Environment.NewLine,
                    PrepareHeaderForMatch = args => args.Header.ToLower(),
                    Comment = '#'
                };
            }
            // extensible dictionary
            public class ExtDictionary<TKey, TValue> : Dictionary<TKey, TValue> where TValue : ICloneable
            {
                // original code
                /*
                    public CloneableDictionary<TKey, TValue> Clone()
                        {
                        CloneableDictionary<TKey, TValue> clone = new CloneableDictionary<TKey, TValue>();
                        foreach (KeyValuePair<TKey, TValue> kvp in this)
                            {
                            clone.Add(kvp.Key, (TValue) kvp.Value.Clone());
                            }
                        return clone;
                        }
                */

                public readonly CvsStuff cvss = new CvsStuff();

                // new one
                public ExtDictionary<TKey, TValue> New()
                {
                    ExtDictionary<TKey, TValue> clone = new ExtDictionary<TKey, TValue>();
                    foreach (KeyValuePair<TKey, TValue> kvp in this)
                    {
                        clone.Add(kvp.Key, (TValue) kvp.Value.Clone());
                    }
                    return clone;
                }

                // extended code
                public ExtDictionary<TKey, TValue> Clone(){
                    return New();
                }

                // convert from other to this
                public void ConvertFromDictionary(Dictionary<TKey, TValue> dict){
                    foreach (KeyValuePair<TKey, TValue> kvp in dict){
                        this.Add(kvp.Key, (TValue) kvp.Value.Clone());
                    }
                }

                public void ConvertFromKeyValuePair(KeyValuePair<TKey, TValue> kvpx){
                    var list = new List<KeyValuePair<TKey, TValue>>{kvpx};
                    var dict = list.ToDictionary(x => x.Key, x => x.Value);
                    // dict.Add(kvpx.Key, kvpx.Value.Clone());
                    /* foreach (KeyValuePair<TKey, TValue> kvp in kvpx){
                        this.Add(kvp.Key, (TValue) kvp.Value.Clone());
                    } */
                    ConvertFromDictionary(dict);
                }

                public void ConvertFromJson(string json){
                    Dictionary<TKey, TValue> dict = JsonConvert.DeserializeObject<Dictionary<TKey, TValue>>(json);

                    ConvertFromDictionary(dict);
                }

                /* public void ConvertFromCsv(string csvtr){
                    string res = "";
                    IEnumerable<T> IEBuffer;
                    ILookup<string, Order> Lookup;
                    using(var sreader = new StringReader(res))
                    using (var csv = new CsvReader(sreader, cvss.cvscfg))
                    {
                        // csv.WriteRecords(this);
                        IEBuffer = csv.GetRecords<T>;
                        Lookup = IEBuffer.ToLookup(o => o.CustomerName);
                    }

                    this = Lookup.ToDictionary(g => g.Key);
                } */

                /* public void ConvertFromCvs(string cvstr){
                    ConvertFromCsv(cvstr);
                } */

                // convert from this to others
                public Dictionary<TKey, TValue> ToDictionary(){
                    Dictionary<TKey, TValue> NewDict = new Dictionary<TKey, TValue>();
                    ExtDictionary<TKey, TValue> edict = this.New();
                    foreach(KeyValuePair<TKey, TValue> kvp in edict){
                        NewDict.Add(kvp.Key, (TValue) kvp.Value.Clone());
                    }
                    return NewDict;
                }

                public List<KeyValuePair<TKey, TValue>> ToLKVP(){
                    var list = this.ToList<KeyValuePair<TKey, TValue>>();

                    return list;
                }

                public string ToJson(){
                    var strs = JsonConvert.SerializeObject(this, Newtonsoft.Json.Formatting.Indented);

                    return strs;
                }

                public string ToCsv(){
                    string res = "";

                    using(var swriter = new StringWriter()){
                        using (var csv = new CsvWriter(swriter, cvss.cvscfg))
                        {
                            csv.WriteRecords(this);
                        }
                        res = swriter.ToString();
                    }

                    return res;
                }

                public string ToCvs(){
                    return ToCsv();
                }

                public string ToXML(){
                    string json = ToJson();
                    XNode node = JsonConvert.DeserializeXNode(json, "Root");
                    return node.ToString();
                }

                public string ToXml(){
                    return ToXML();
                }
            }
        }

and here is the problematic code

          static ExtDictionary<string, string> TemplaeDict = new ExtDictionary<string, string>();
          static ExtDictionary<string, string> JSONDict = TemplaeDict.New();

I get this error when running "dotnet build"

C:\snek\Program.cs(151,40): error CS0311: The type 'string' cannot be used as type parameter 'TValue' in the generic type or method 'ExtDictionary<TKey, TValue>'. There is no implicit reference conversion from 'string' to 'System.IFormattable'. [C:\snek\snek.csproj]

C:\snek\Program.cs(152,40): error CS0311: The type 'string' cannot be used as type parameter 'TValue' in the generic type or method 'ExtDictionary<TKey, TValue>'. There is no implicit reference conversion from 'string' to 'System.IFormattable'. [C:\snek\snek.csproj]

Can someone help me with the code, Is something wrong with the main code or the edict I have looked around and there is no good answer.

Here are some links The reference of the game The nuget code

3 Answers3

1

Try FormattableString instead of string. Ref: Difference between String, FormattableString, IFormattable

AlanK
  • 1,827
  • 13
  • 16
  • Can you please explain the problem? – MXPSQL Server 20953 onetechguy Oct 03 '21 at 05:14
  • @MXPSQLServer20953onetechguy I'm trying to work it out. I know that Newtonsoft tries to use IFormattable here and there "where possible". Haven't had time to dig in but `FormattableString` should get you past the error you have here. Will revert in a couple of hours if nobody else has cracked it by then. – AlanK Oct 03 '21 at 05:31
  • @MXPSQLServer20953onetechguy your code compiles fine for me (VS2019 & `dotnet` from command line - for .NET 5 and Fx4.6.2 through 4.8). Please update your question with what versions of .Net, Newtonsoft Json, CsvHelper you are using. All I did was copy your code into a new console app and add current version Newtonsoft and CsvHelper packages; you might like to do this and then - assuming its works - compare project files, packages.config etc and answer your own question. – AlanK Oct 03 '21 at 08:10
  • I don't use vs 2019, only vs code. VS 2019 is just too big for my heap of code. – MXPSQL Server 20953 onetechguy Oct 04 '21 at 00:26
  • As I said it works for me from the command line as well, which means it has to be something else - other code and/or environment, mix of versions, configuration. You're going to have to share those details or work it out yourself because what you've shown so far seems fine. – AlanK Oct 04 '21 at 04:41
  • The Iformattable was applying to the TValue, not the whole class – MXPSQL Server 20953 onetechguy Oct 13 '21 at 11:16
0

It looks ok. Did you use the other ExtDictionary class (same name but difference namespace/module)?

Long Nguyen Duc
  • 1,317
  • 1
  • 8
  • 13
0
using System;
using System.IO;
using CsvHelper;
using System.Xml;
using System.Linq;
using System.Xml.Linq;
using Newtonsoft.Json;
using System.Collections;
using System.Globalization;
using CsvHelper.Configuration;
using System.Collections.Generic;
using System.Runtime.InteropServices;

namespace MXPSQL.EDict{
    public class CvsStuff{
        public CsvConfiguration cvscfg = new CsvConfiguration(CultureInfo.InvariantCulture)
        {
            NewLine = Environment.NewLine,
            PrepareHeaderForMatch = args => args.Header.ToLower(),
            Comment = '#'
        };
    }
    // extensible dictionary
    public class ExtDictionary<TKey, TValue> : Dictionary<TKey, TValue>, IFormattable where TValue : ICloneable
    {
        // original code
        /*
            public CloneableDictionary<TKey, TValue> Clone()
                {
                CloneableDictionary<TKey, TValue> clone = new CloneableDictionary<TKey, TValue>();
                foreach (KeyValuePair<TKey, TValue> kvp in this)
                    {
                    clone.Add(kvp.Key, (TValue) kvp.Value.Clone());
                    }
                return clone;
                }
        */

        public readonly CvsStuff cvss = new CvsStuff();

        // new one
        public ExtDictionary<TKey, TValue> New()
        {
            ExtDictionary<TKey, TValue> clone = new ExtDictionary<TKey, TValue>();
            foreach (KeyValuePair<TKey, TValue> kvp in this)
            {
                clone.Add(kvp.Key, (TValue) kvp.Value.Clone());
            }
            return clone;
        }

        // extended code
        public ExtDictionary<TKey, TValue> Clone(){
            return New();
        }

        // convert from other to this
        public void ConvertFromDictionary(Dictionary<TKey, TValue> dict){
            foreach (KeyValuePair<TKey, TValue> kvp in dict){
                this.Add(kvp.Key, (TValue) kvp.Value.Clone());
            }
        }

        public void ConvertFromKeyValuePair(KeyValuePair<TKey, TValue> kvpx){
            var list = new List<KeyValuePair<TKey, TValue>>{kvpx};
            var dict = list.ToDictionary(x => x.Key, x => x.Value);
            // dict.Add(kvpx.Key, kvpx.Value.Clone());
            /* foreach (KeyValuePair<TKey, TValue> kvp in kvpx){
                this.Add(kvp.Key, (TValue) kvp.Value.Clone());
            } */
            ConvertFromDictionary(dict);
        }

        public void ConvertFromJson(string json){
            Dictionary<TKey, TValue> dict = JsonConvert.DeserializeObject<Dictionary<TKey, TValue>>(json);

            ConvertFromDictionary(dict);
        }

        /* public void ConvertFromCsv(string csvtr){
            string res = "";
            IEnumerable<T> IEBuffer;
            ILookup<string, Order> Lookup;
            using(var sreader = new StringReader(res))
            using (var csv = new CsvReader(sreader, cvss.cvscfg))
            {
                // csv.WriteRecords(this);
                IEBuffer = csv.GetRecords<T>;
                Lookup = IEBuffer.ToLookup(o => o.CustomerName);
            }

            this = Lookup.ToDictionary(g => g.Key);
        } */

        /* public void ConvertFromCvs(string cvstr){
            ConvertFromCsv(cvstr);
        } */

        // convert from this to others
        public Dictionary<TKey, TValue> ToDictionary(){
            Dictionary<TKey, TValue> NewDict = new Dictionary<TKey, TValue>();
            ExtDictionary<TKey, TValue> edict = this.New();
            foreach(KeyValuePair<TKey, TValue> kvp in edict){
                NewDict.Add(kvp.Key, (TValue) kvp.Value.Clone());
            }
            return NewDict;
        }

        public List<KeyValuePair<TKey, TValue>> ToLKVP(){
            var list = this.ToList<KeyValuePair<TKey, TValue>>();

            return list;
        }

        public string ToJson(){
            var strs = JsonConvert.SerializeObject(this, Newtonsoft.Json.Formatting.Indented);

            return strs;
        }

        public string ToCsv(){
            string res = "";

            using(var swriter = new StringWriter()){
                using (var csv = new CsvWriter(swriter, cvss.cvscfg))
                {
                    csv.WriteRecords(this);
                }
                res = swriter.ToString();
            }

            return res;
        }

        public string ToCvs(){
            return ToCsv();
        }

        public string ToString(string? format, IFormatProvider? formatProvider){
            return ToCvs();
        }

        public string ToXML(){
            string json = ToJson();
            XNode node = JsonConvert.DeserializeXNode(json, "Root");
            return node.ToString();
        }

        public string ToXml(){
            return ToXML();
        }
    }
}

A very simple fix, just move the I formattable before the where. The problem is that the iformattable is placed on the TValue, not the whole class.