我创建了一个包含两个项目的项目。 一个是控制台应用程序,而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。
是否有任何解决方法。
请帮我解决这个问题。
提前致谢。
答案 0 :(得分:5)
您似乎正在使用CastByExample技巧。它不会在程序集之外工作,因为编译器在每个程序集中生成两个独立的匿名类型。
最好的解决方法是使用自己的类型。并在共同集会中分享
public class MyData
{
public int ID {get;set;}
public string Name{get;set;}
}
答案 1 :(得分:4)
匿名类型仅在以下情况下共享相同的编译时类型:
如果程序集中的两个或多个匿名对象初始值设定项 指定 具有相同顺序且具有相同顺序的属性序列 相同的名称和类型,编译器将对象视为实例 相同的类型。
你有第一个,但第二个没有。因此,即使两个匿名类型看起来相同,就C#和运行时而言,它们是两个完全不同的,不兼容的类型。
理想情况下,匿名类型应不从方法中传回(因为您现在发现)并不完全可用。
在这种情况下,您最好只在ClassLibrary1
中定义一个类,以包含ID
和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()
意味着你想要一些动态创建的内容,或者返回不同的类型。也许有必要提供更多的背景,重构或更好的设计。