如何在.NET中将类型A的对象转换为B类?

时间:2013-11-11 15:54:58

标签: c# asp.net .net object casting

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

我将类库项目中的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。

是否有任何解决方法。

请帮我解决这个问题。

提前致谢。

2 个答案:

答案 0 :(得分:5)

您似乎正在使用CastByExample技巧。它不会在程序集之外工作,因为编译器在每个程序集中生成两个独立的匿名类型。

最好的解决方法是使用自己的类型。并在共同集会中分享

public class MyData
{
   public int ID {get;set;}
   public string Name{get;set;}
}

答案 1 :(得分:4)

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

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

from the MSDN

  

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

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

理想情况下,匿名类型应从方法中传回(因为您现在发现)并不完全可用。

在这种情况下,您最好只在ClassLibrary1中定义一个类,以包含IDName。这样做会强有力地键入整个过程,并且无需基本上复制您返回的信息的结构。


为您举例说明您现在所做的代码(或多或少):

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()意味着你想要一些动态创建的内容,或者返回不同的类型。也许有必要提供更多的背景,重构或更好的设计。