【问题标题】:Cannot convert from custom object to object or dynamic无法从自定义对象转换为对象或动态
【发布时间】:2020-02-27 13:20:45
【问题描述】:

我有一个列表,我想用不同类型的对象填充它,尝试使用 object\dynamic 来完成它,但它没有,即使在投射时也是如此。 使用 asp.net 核心。 查看我的代码:

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;
}

【问题讨论】:

  • new List&lt;string, object&gt; 是错字吗?
  • List&lt;T&gt; 只接受一个类型参数——这里的List&lt;string, object&gt; 到底是什么意思?你的意思是Dictionary&lt;string, object&gt;?要么...?注意:您不能将 Dictionary&lt;string, Employee&gt; 转换为 Dictionary&lt;string, object&gt; - 这不是“方差”的工作原理
  • 类型错误——抱歉,这是我写的伪代码。尽快修复它
  • @Johnathan Barclay- 我修复了代码
  • @Marc Gravell - 我修复了代码

标签: c# dictionary object asp.net-core dynamicobject


【解决方案1】:

根据您要执行的操作,我可以看到两种解决方案:

创建两个不同字典的列表

    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;
    }

创建一个包含所有值的字典

    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;
    }

【讨论】:

    【解决方案2】:

    这里有几个问题,都与方差有关。

    这不起作用,因为 List&lt;T&gt; 或 .NET 中的任何其他类不支持方差。

    换句话说,T 必须是特定类型,并且不像非泛型类型那样尊重继承/可替换性。

    同样,对于Dictionary&lt;TKey, TValue&gt;TValue 不是变体,所以不能简单地使用object 作为值。

    另一方面,IEnumerable&lt;out T&gt; 是协变的,因此您可以这样做:

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

    使用IDictionary,因为它是Dictionary&lt;string, Employee&gt;Dictionary&lt;string, Customer&gt; 的唯一共同祖先(对象除外)。

    这可能满足您的要求,但您并不清楚您尝试使用 getDifferentItems 方法实现的目的。

    更多关于方差的信息可以在here找到。

    【讨论】:

    • 谢谢 - 它基本上用于休息方法 - 获取静态查找表的集合。在我的代码中,容器(列表)被替换为字典>以获取表名的标识符作为键,并将其内容(键,值)作为值
    【解决方案3】:

    我会亲自制作一个接口,例如 IPerson,它具有员工和客户的所有属性,例如姓名、地址、ID 等。

    设置您的客户和员工类以实施 IPerson

    然后在您的字典中使用 IPerson,您可以将对象添加到其中。

    这里有一些代码:

    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);
            }
        }
    

    【讨论】:

    • 这是我最初的想法,但类型已经存在,非常不同,没有相似的属性
    • 如果这两种类型没有相似的属性,我认为你应该更多地考虑做你所做的事情的目的。如果客户和员工不相似,您为什么要向呼叫者返回他们的列表?既然你说它是一种休息方法,也许应该有一个单独的员工和客户调用,或者应该有一个包含两个集合的整体对象,1个用于员工,1个用于客户。此外,IPerson 可以拥有各种属性的联合,您只能根据它是 Customer 还是 Employee 来实现。
    • 这两个对象只是示例。我引用的表已经映射到字典类型,它们的值可以是例如原子字符串或对象。另外 - 我想为所有查找打一个电话。
    • 您是否考虑过制作一个包含字符串和数据表的字典,因为您实际上只是想返回所有静态查找表?
    • 没有,没想到,我把数据传成json,不确定有没有好处
    【解决方案4】:

    这是另一个解决方案:

        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;}
        }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-05-01
      • 1970-01-01
      • 1970-01-01
      • 2012-10-26
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多