仿制药和铸造 [英] Generics and casting
问题描述
我有一个包含各种来源数据的xml文件。例如:
< root>
<帐户>
< Id> 1< / Id>
<名称> Somename< /名称>
< City> Somecity< / City>
< ContactPersons>
< ContactPerson>
< Id> 1< / Id>
<名称> Somename< /名称>
< / ContactPerson>
< ContactPerson>
< Id> 2< / Id>
<名称> Somename2< /名称>
< / ContactPerson>
< / ContactPersons>
< /帐户>
< / root> ;
我创建了一个通用的businesscollection(名为BusinessCollection)和一个
的业务类(名为BusinessObject)。然后我创建了一个名为Account的特定
业务类,另一个名为ContactPerson的业务类。它们都来自BusinessObject类。
我使用以下帐户创建了一个businesscollection实例:
BusinessCollection<帐户> collection = new BusinessCollection
< Account>();
我还制作了一个解析器,将xml转换为正确的
商务课程。因此,在上述数据的情况下,我提供了一个
BusinessCollection< Account>的实例。然后我创建帐户对象并将
添加到集合中。这都是使用反射和一些
XPath类完成的。
解析器具有folling方法签名:
public static void ParseToBusinessObjects< T>(BusinessCollection< T>
集合,XPathDocument文档)其中T:BusinessObject
到目前为止一切顺利。但是现在我也想要子集来解析。在xml
数据中,ContactPersons将是我的子集合(属性名称为
相同)。如果我的解析器检测到子集合,它将获得当前的
实例(使用反射)。然后我想再次调用我的输入法
这个集合(递归)
但是当我这样做时:
BusinessCollection < BusinessObject的> subCollection =(BusinessCollection
< BusinessObject>)property.GetValue(instance,null);
我得到一个InvalidCastException,说我无法转换a
BusinessCollection< ContactPerson>和一个
BusinessCollection< BusinessObject>。
当我将其更改为时,它是相同的:
BusinessCollection< T> subCollection =(BusinessCollection< T>)
property.GetValue(instance,null);
我希望有人知道如何解决这个问题,因为它让我疯狂。 />
I have a xml file with data from various sources. For example:
<root>
<Account>
<Id>1</Id>
<Name>Somename</Name>
<City>Somecity</City>
<ContactPersons>
<ContactPerson>
<Id>1</Id>
<Name>Somename</Name>
</ContactPerson>
<ContactPerson>
<Id>2</Id>
<Name>Somename2</Name>
</ContactPerson>
</ContactPersons>
</Account>
</root>
I created a generic businesscollection (named BusinessCollection) and a
business class (named BusinessObject). Then I created a specific
business class named Account en another one called ContactPerson. They
both derive from the BusinessObject class.
I created a instance of a businesscollection with accounts using:
BusinessCollection <Account> collection = new BusinessCollection
<Account>();
I also made a parser that ''translates'' the xml into the correct
business classes. So in case of the data above I provide a instance of
BusinessCollection <Account>. Then I create Account objects and add
them to the collection. This is all done using reflection and some
XPath classes.
The parser has the folling method signature:
public static void ParseToBusinessObjects <T>(BusinessCollection <T>
collection, XPathDocument document) where T : BusinessObject
So far so good. But now I also want subcollections to parse. In the xml
data ContactPersons will be my subcollection (property is named the
same). If my parser detects a subcollection it will get the current
instance (using reflection). I then want to call my entry method again
for this collection (recursive)
However when I do this:
BusinessCollection <BusinessObject> subCollection = (BusinessCollection
<BusinessObject>) property.GetValue(instance, null);
I get a InvalidCastException saying I can''t convert between a
BusinessCollection<ContactPerson> and a
BusinessCollection<BusinessObject>.
Its the same when I change it to :
BusinessCollection <T> subCollection = (BusinessCollection <T>)
property.GetValue(instance, null);
I hope someone knows how to solve this because its driving me nuts.
推荐答案
Alexander van Doormalen写道:
Alexander van Doormalen wrote:
我有一个包含各种来源数据的xml文件。例如:
< root>
<帐户>
< Id> 1< / Id>
<名称> Somename< /名称> < br&>< City> Somecity< / City>
< ContactPersons>
< ContactPerson>
< Id> 1< / Id>
<名称> Somename< ; /名称>
< / ContactPerson>
< ContactPerson>
< Id> 2< / Id>
<名称> Somename2< /名称>
< / ContactPerson>
< / ContactPersons>
< / Account>
< / root>
我创建了一个通用的businesscollection(名为BusinessCollection)和/或业务类(名为BusinessObject)。然后我创建了一个名为Account的特定商业类,另一个名为ContactPerson的商业类。它们都来自BusinessObject类。
我使用以下方法创建了一个带有帐户的businesscollection实例:
BusinessCollection< Account> collection = new BusinessCollection
< Account>();
我还制作了一个解析器,将xml翻译成正确的业务类。因此,在上述数据的情况下,我提供了一个
BusinessCollection< Account>的实例。然后我创建帐户对象并将它们添加到集合中。这都是使用反射和一些
XPath类完成的。
解析器具有folling方法签名:
public static void ParseToBusinessObjects< T>(BusinessCollection< T>
集合,XPathDocument文档)其中T:BusinessObject
到目前为止一切顺利。但是现在我也想要子集来解析。在
xml数据中,ContactPersons将是我的子集合(属性名称
相同)。如果我的解析器检测到子集合,它将获得
当前实例(使用反射)。然后我想再次为这个集合调用我的条目
方法(递归)
然而,当我这样做时:
BusinessCollection< BusinessObject> subCollection =
(BusinessCollection< BusinessObject>)property.GetValue(instance,
null);
我得到一个InvalidCastException,说我不能在
BusinessCollection< ContactPerson>和/或BusinessCollection< BusinessObject>。
当我将其更改为时,它是相同的:
BusinessCollection< T> subCollection =(BusinessCollection< T>)
property.GetValue(instance,null);
I have a xml file with data from various sources. For example:
<root>
<Account>
<Id>1</Id>
<Name>Somename</Name>
<City>Somecity</City>
<ContactPersons>
<ContactPerson>
<Id>1</Id>
<Name>Somename</Name>
</ContactPerson>
<ContactPerson>
<Id>2</Id>
<Name>Somename2</Name>
</ContactPerson>
</ContactPersons>
</Account>
</root>
I created a generic businesscollection (named BusinessCollection) and
a business class (named BusinessObject). Then I created a specific
business class named Account en another one called ContactPerson. They
both derive from the BusinessObject class.
I created a instance of a businesscollection with accounts using:
BusinessCollection <Account> collection = new BusinessCollection
<Account>();
I also made a parser that ''translates'' the xml into the correct
business classes. So in case of the data above I provide a instance of
BusinessCollection <Account>. Then I create Account objects and add
them to the collection. This is all done using reflection and some
XPath classes.
The parser has the folling method signature:
public static void ParseToBusinessObjects <T>(BusinessCollection <T>
collection, XPathDocument document) where T : BusinessObject
So far so good. But now I also want subcollections to parse. In the
xml data ContactPersons will be my subcollection (property is named
the same). If my parser detects a subcollection it will get the
current instance (using reflection). I then want to call my entry
method again for this collection (recursive)
However when I do this:
BusinessCollection <BusinessObject> subCollection =
(BusinessCollection <BusinessObject>) property.GetValue(instance,
null);
I get a InvalidCastException saying I can''t convert between a
BusinessCollection<ContactPerson> and a
BusinessCollection<BusinessObject>.
Its the same when I change it to :
BusinessCollection <T> subCollection = (BusinessCollection <T>)
property.GetValue(instance, null);
这不是支持的。它被称为协方差,并且在.NET泛型中不支持
。 BusinessCollection< BusinessObject的>不是超级类型
的BusinessCollection<联系>,即使它看起来像它。
这就是演员表演失败的原因。
>
你可以轻松解决它。实现一个接口。接口是
如果泛型类型描述符
发生变化,这是进行泛型编程的一般方法。因此,在您的BusinessCollecttion< T>上,您实施了
IBusinessCollection。这是一个非通用的界面,使用相同的
方法。
你现在可以这样做:
IBusinessCollection subCollection =
(IBusinessCollection)property.Getvalue(instance,null);
并再次调用你的代码。
Frans
-
------------------------------- -----------------------------------------
铅LLBLGen Pro的开发人员,.NET的高效O / R映射器
LLBLGen Pro网站: http://www.llblgen.com
我的.NET博客: http://weblogs.asp.net/fbouma
Microsoft MVP(C#)
-------- -------------------------------------------------- --------------
This isn''t supported. It''s called covariance, and that''s not supported
in .NET generics. BusinessCollection<BusinessObject> isn''t a supertype
of BusinessCollection<Contact>, even though it might look like it.
That''s why casts fail.
You can solve it easily though. Implement an interface. Interfaces are
a general way to do generic programming if the generic type descriptor
changes. So, on your BusinessCollecttion<T>, you implement
IBusinessCollection. That''s a non-generic interface, with the same
methods.
You can now do:
IBusinessCollection subCollection =
(IBusinessCollection)property.Getvalue(instance, null);
and call your code again.
Frans
--
------------------------------------------------------------------------
Lead developer of LLBLGen Pro, the productive O/R mapper for .NET
LLBLGen Pro website: http://www.llblgen.com
My .NET blog: http://weblogs.asp.net/fbouma
Microsoft MVP (C#)
------------------------------------------------------------------------
Frans Bouma [C#MVP]< pe ************ ******@xs4all.nl>写道:
Frans Bouma [C# MVP] <pe******************@xs4all.nl> wrote:
当我将其更改为时,它是相同的:
BusinessCollection< T> subCollection =(BusinessCollection< T>)
property.GetValue(instance,null);
Its the same when I change it to :
BusinessCollection <T> subCollection = (BusinessCollection <T>)
property.GetValue(instance, null);
这不受支持。它被称为协方差,并且在.NET泛型中不支持
。 BusinessCollection< BusinessObject的>虽然它可能看起来像它,但它并不是BusinessCollection< Contact>的超级类型。
这就是演员表演失败的原因。
This isn''t supported. It''s called covariance, and that''s not supported
in .NET generics. BusinessCollection<BusinessObject> isn''t a supertype
of BusinessCollection<Contact>, even though it might look like it.
That''s why casts fail.
只是一个小小的修正 - 它在C#泛型中不受支持。显然
..NET本身同时支持协方差和逆变,但C#没有b $ b暴露它。有关详细信息,请参阅以下链接 - 这是非常有趣的
东西...
http://blogs.msdn.com/rmbyers/archiv...16/375079.aspx
-
Jon Skeet - < sk *** @ pobox.com>
http://www.pobox.com/~skeet 博客: http://www.msmvps.com/jon.skeet
如果回复该群组,请不要给我发邮件太多
Just a tiny correction - it''s not supported in C# generics. Apparently
..NET itself supports both covariance and contravariance, but C# doesn''t
expose it. See the following link for details - it''s fascinating
stuff...
http://blogs.msdn.com/rmbyers/archiv...16/375079.aspx
--
Jon Skeet - <sk***@pobox.com>
http://www.pobox.com/~skeet Blog: http://www.msmvps.com/jon.skeet
If replying to the group, please do not mail me too
对于那些不可能的事情:(。我希望它会出现在这个特性中。
因为使用接口isn因为各种原因(比如
内部方法需要在对象上调用等),所以我可能会这样做。所以我通过创建一个来解决'b $''期望普通对象的内部方法。
然后我使用reflec调用该集合上的Add方法(
作为对象传递)
MethodInfo info = collection.GetType()。GetMethod("添加);
object [] paramaters = new object [1];
paramaters [0] = businessObject;
info.Invoke(集合,参数);
不是一个非常干净的方式,但它现在可以工作。
Thnx伙伴们的帮助!
To bad thats not possible yet :(. I hope it will be in the feature.
Since using interfaces isn''t possibe because of various reasons (like
internal methods that need to be called on the object etc). So I
''solved'' it by creating an internal method that expects a plain object.
I then use reflection to call the Add method on that collection (which
is passed as an object)
MethodInfo info = collection.GetType().GetMethod("Add");
object[] paramaters = new object[1];
paramaters[0] = businessObject;
info.Invoke(collection, paramaters);
Not a very clean way but it works for now.
Thnx guys for the help!
这篇关于仿制药和铸造的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!