0

I have a List which I would like to populate with different types of objects, trying to do it with object\dynamic, but it doesn't, even when casting. using asp.net core. See my code:

public Dictionary<string, Employee> getEmployees(); //This method returns a dictionary of string as a key and Employee as a value.
public Dictionary<string, customer>()> getCustomers(); //same principal


public List<Dictionary<string, object>> getDifferentItems()
{
   List<Dictionary<string, object>> listOfItems = new List<Dictionary<string, object>>();
   listOfItems.add(getEmployees()); //Error
   listOfItems.add(getCustomers()); //Error
   return listOfItems;
}
Guy E
  • 1,775
  • 2
  • 27
  • 55

4 Answers4

1

Depending on what you are trying to do, I can see two solutions:

Create a list of TWO different dictionaries

    public Dictionary<string, Employee> getEmployees() {
        return new Dictionary<string, Employee>();
    }
    public Dictionary<string, Customer> getCustomers() {
        return new Dictionary<string, Customer>();
    }


    public List<Dictionary<string, object>> getDifferentItems()
    {
        List<Dictionary<string, object>> listOfItems = new List<Dictionary<string, object>>();
        listOfItems.Add(this.getEmployees().ToDictionary(entry => (string)entry.Key,
                  entry => (object)entry.Value)); 
        listOfItems.Add(this.getCustomers().ToDictionary(entry => (string)entry.Key,
                  entry => (object)entry.Value)); 
        return listOfItems;
    }

Create one dictionary with all the values

    public Dictionary<string, Employee> getEmployees() {
        return new Dictionary<string, Employee>();
    }
    public Dictionary<string, Customer> getCustomers() {
        return new Dictionary<string, Customer>();
    }


    public Dictionary<string, object> getDifferentItems()
    {
        Dictionary<string, object> listOfItems = new Dictionary<string, object>();
        foreach (var entry in getEmployees()) {
            listOfItems.Add(entry.Key, entry.Value);
        }
        foreach (var entry in getCustomers()) {
            listOfItems.Add(entry.Key, entry.Value);
        }
        return listOfItems;
    }
Athanasios Kataras
  • 25,191
  • 4
  • 32
  • 61
0

There are a couple of issues here, both related to variance.

This won't work because List<T>, or any other class in .NET for that matter, does not support variance.

In other words T has to be a specific type, and does not respect inheritance / substitutability as with non-generic types.

Similarly, for Dictionary<TKey, TValue>, TValue is not variant, so you can't simply use object as the value.

IEnumerable<out T> on the other hand is covariant so you could do this:

public IEnumerable<IDictionary> getDifferentItems()
{
   yield return getEmployees();
   yield return getCustomers();
}

IDictionary is used, as it is the only common ancestor (other than object) to Dictionary<string, Employee> and Dictionary<string, Customer>.

This may satisfy your requirements, but you don't make clear whay you are trying to achive with your getDifferentItems method.

More information on variance can be found here.

Johnathan Barclay
  • 18,599
  • 1
  • 22
  • 35
  • thanks - It is basically used in a rest method - to get collection of static lookup tables. In my code the container (List) is replaced by a dictionary> to get identifier for the table name as a key, and its content (key, value) as a value – Guy E Feb 27 '20 at 13:45
0

I'd personally make an interface, such as IPerson that has all the properties of Employees and Customers, such as Name, Address, ID, etc.

Set up your Customer and employee classes to implement IPerson

Then use a IPerson in your dictionary and you can add to the objects to that.

Here's some code:

public class Employee : IPerson
    {
        public int ID { get; set; }

        public string Name { get; set; }
    }

    public class Customer : IPerson
    {
        public int ID { get; set; }

        public string Name { get; set; }
    }

    public interface IPerson
    {
        int ID { get; set; }

        string Name { get; set; }
    }
    public class Test
    {
        public void MyTest()
        {
            List<Dictionary<string, IPerson>> listOfItems = new List<Dictionary<string, IPerson>>();

            Dictionary<string, IPerson> myEmployees = new Dictionary<string, IPerson>();
            string someString = "blah";
            Employee e = new Employee();
            e.Name = "Bob";
            e.ID = 1;

            myEmployees.Add(someString, e);

            Dictionary<string, IPerson> myCustomers = new Dictionary<string, IPerson>();
            string someOtherString = "blah";
            Customer c = new Customer();
            c.Name = "Robert";
            c.ID = 2;

            myCustomers.Add(someOtherString, c);

            listOfItems.Add(myEmployees);
            listOfItems.Add(myCustomers);
        }
    }
chris-crush-code
  • 1,114
  • 2
  • 8
  • 17
  • this was my initial thought, but the types are already there, very different, with no similar properties – Guy E Feb 27 '20 at 13:48
  • If the two types don't have similiar properties I think you should give more thought to the purpose of doing what your doing. If Customers and Employees aren't similiar why are you returning a list of them intermingled to the caller? Since you said it's a rest method, maybe there should be a separate calls for employees and customers or maybe there should be one overall object that contains two collections, 1 for employees and 1 for customers. Also, IPerson could have a union of the various properties and you only implement based on if it's Customer or Employee. – chris-crush-code Feb 27 '20 at 13:52
  • these 2 objects are just examples. The tables I refer to were already mapped to dictionary types where their value can be, for example, an atomic string or an object. Additionally - I would like to make a one call for all the lookups. – Guy E Feb 27 '20 at 13:56
  • Have you thought about making a dictionary of string and datatable since you're essentially just trying to return all the static lookup tables? – chris-crush-code Feb 27 '20 at 14:08
  • No, not thought of it, I passing the data as json, I'm not sure that it has benefits – Guy E Feb 27 '20 at 14:26
0

Here is another solution :

    public class Test
    {
        Dictionary<string, object> listOfItems = new Dictionary<string, object>();
        List<Employee> employees = new List<Employee>();
        List<customer> customers = new List<customer>();
        public Dictionary<string, object> getEmployees()
        {
            return employees.GroupBy(x => x.name, y => (object)y).ToDictionary(x => x.Key, y => y.FirstOrDefault());

        }//This method returns a dictionary of string as a key and Employee as a value.
        public Dictionary<string, object> getCustomers()
        {
            return customers.GroupBy(x => x.name, y => (object)y).ToDictionary(x => x.Key, y => y.FirstOrDefault());
        } //same principal 
        public Dictionary<string, object> getDifferentItems()
        {
            listOfItems = getEmployees();
            listOfItems.Concat(getCustomers());
            return listOfItems;
        }
    }
    public class Employee
    {
        public string name { get;set;}
    }
    public class customer
    {
        public string name { get;set;}
    }
jdweng
  • 33,250
  • 2
  • 15
  • 20