4

我创建了一个包含两个项目的项目。一个是控制台应用程序,另一个是类库项目。

我将类库项目中的 dll 引用添加到控制台应用程序中。

现在,当我从类库项目返回一个对象时,可以在控制台应用程序中检索它,但如果我尝试强制转换它,它就不起作用。

它抛出错误,因为无法将类型 a 转换为类型 b。

我在这个错误中挣扎了好几个小时。

我的类库项目代码:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace ClassLibrary1
{
    public class Class1
    {
        public object dyn()
        {
            var obj = new { ID = 2, Name = "Rajesh" };
            return obj;
        }
    }
}

在上面我返回了一个列表作为对象。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Linq;
using System.Data.SqlClient;
using System.Collections;
using System.Data;
using ClassLibrary1;
using System.Reflection;
using System.ComponentModel;
namespace ConsoleApplication2
{
    public class Program
    {
        public static void Main(string[] args)
        {
            Program objPgm = new Program();
            Class1 objCls=new Class1();            
            object obj = objCls.dyn();
            var list = objPgm.cast(obj, new { ID = 0, Name = "" });
        }

        public  T cast<T>(object obj,T type) 
        {          
            return (T)obj; 
        }
}

在上面的代码中,我从类库项目中检索了对象,并在尝试强制转换时抛出了 InvalidCastException。

有什么解决办法。

请在这个问题上帮助我。

提前致谢。

4

2 回答 2

5

看来您正在使用CastByExample技巧。由于编译器在每个程序集中生成两个独立的匿名类型,因此它不会在程序集中起作用。

最好的解决方法是使用您自己的类型。并在公共装配中分享

public class MyData
{
   public int ID {get;set;}
   public string Name{get;set;}
}
于 2013-11-11T16:01:34.153 回答
4

匿名类型仅在以下情况下共享相同的编译时类型:

  • 它们共享完全相同的参数名称、类型和顺序
  • 它们存在于同一个程序集中

从 MSDN

如果程序集中的两个或多个匿名对象初始值设定项指定顺序相同且名称和类型相同的属性序列,则编译器会将对象视为相同类型的实例。

第一个你有,第二个你没有。因此,即使这两种匿名类型看起来相同,但就 C# 和运行时而言,它们是两种完全不同的、不兼容的类型。

理想情况下,不应将匿名类型方法中传回,因为它们(正如您现在发现的那样)并不完全可用。

在这种情况下,你最好简单地在你的类中定义一个ClassLibrary1包含IDand的类Name。这样做强烈地键入了整个过程,并消除了从本质上复制您返回的信息结构的需要。


举个例子说明你现在的代码(或多或少)在做什么:

namespace ClassLibrary1
{
    internal class ClassLibrary1_AnonObj1
    {
        public int ID { get; set; }
        public string Name { get; set; }
    }

    public class Class1
    {
        public object dyn()
        {
            var obj = new ClassLibrary1_AnonObj1 { ID = 2, Name = "Rajesh" };
            return obj;
        }
    }
}

namespace ConsoleApplication2
{
    internal class ClassLibrary2_AnonObj2
    {
        public int ID { get; set; }
        public string Name { get; set; }
    }

    public class Program
    {
        public static void Main(string[] args)
        {
            Program objPgm = new Program();
            Class1 objCls=new Class1();            
            object obj = objCls.dyn();
            var list = objPgm.cast(obj, new ClassLibrary2_AnonObj2 { ID = 0, Name = "" });
        }

        public  T cast<T>(object obj,T type) 
        {          
            return (T)obj; 
        }
    }
}

这就像铸造:

ClassLibrary1_AnonObj1 obj = new ClassLibrary1_AnonObj1();
ClassLibrary2_AnonObj2 obj2 = (ClassLibrary2_AnonObj2)obj;

这就是它会失败的原因,因为这两种类型看起来完全不同。相反,如果您声明并使用自己的类:

namespace ClassLibrary1
{
    public class MyInfo
    {
        public int ID { get; set; }
        public string Name { get; set; }
    }

    public class Class1
    {
        public MyInfo dyn()
        {
            var obj = new MyInfo { ID = 2, Name = "Rajesh" };
            return obj;
        }
    }
}

namespace ConsoleApplication2
{
    public class Program
    {
        public static void Main(string[] args)
        {
            Program objPgm = new Program();
            Class1 objCls=new Class1();            
            MyInfo obj = objCls.dyn();
        }
    }
}

这消除了铸造的任何需要。或者,如果您需要它来保持它返回object,您可以在此时简单地转换它:

Class1 objCls=new Class1();            
MyInfo obj = (MyInfo)objCls.dyn();

虽然我怀疑您的使用dyn()暗示您打算有一些动态创建的内容,或返回不同的类型。也许需要更多的上下文、重构或更好的设计。

于 2013-11-11T16:03:11.430 回答