如何在c#中创建通用方法并传递公共类名? [英] How to create common method in c# and pass common class name ?

查看:71
本文介绍了如何在c#中创建通用方法并传递公共类名?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述



我有一个将xml反序列化为类对象的常用方法。

我有一种方法将XML反序列化为类对象。

我有一个关于如何将公共类名传递给方法返回类型的查询,所以我可以传递任何类名并用于全局目的。

以下是我的方法 - >

  public   static  classsname DeserializeXML( string  inputXml)
{
classsname returnDto;
string inpXML = inputXml.Replace( );
使用(MemoryStream ms = ConvertXmlToStream(inpXML))
{
XmlSerializer seralize = XmlSerializer( typeof (classsname));
使用(XmlTextReader reader = new XmlTextReader(ms))
{
returnDto =(classsname)seralize.Deserialize(reader);

reader.Close();
}
}

return returnDto;
}



在课程名称中我需要保留以便它可以达到全球目的。



谢谢...

解决方案

我必须说,这是设计通用序列化的一种非常天真的尝试。但是,你已经遇到了一个主要困难:如何处理多态集。



我知道如何真正做到细节,但解释它可以拿一整篇非常大的文章。我可以简单地建议你看一下 Data Contract 的实现( http:/ /msdn.microsoft.com/en-us/library/ms733127.aspx [ ^ ]),但是,此时,我不知道在哪里可以找到它的源代码,也不确定Microsoft是否提供了此源代码。 (.NET的源代码之前是可用的,仅用于学习和调试目的,但它不包括Data Contract;我不确定您是否可以在此时找到更新的源代码;您可以尝试找出答案。此外,您可以找到 System.Xml.Serialization.XmlSerializer 的源代码, http://msdn.microsoft.com/en-us/library/system.xml.serialization.xmlserializer.aspx [ ^ ]。)



所以,我只能关注一个基本问题:如何通过从序列化流中获取的类名来创建类的实例。



基本上,这都是通过Reflection完成的。



首先,您可以采取一些装配或一组装配中的所有类型:

http://msdn.microsoft.com/en-us/library/system.type.aspx [ ^ ],

http://msdn.microsoft.com/en-us/library/system。 reflection.assembly.gettypes.aspx [ ^ ]。



您可以根据类型名称扫描所有类型,并找出 System.Type 具有匹配的名称。这是非常无效的,但您可以以某种方式缓存在第一次尝试期间找到的所有类型,以备将来使用,因此您不会重复这样做。一个问题是:如果使用简单的类型名称,您可能会面对两种不同类型之间的分辨率,具有不同的完全限定名称,但具有相同的简单名称。您应该假设所有简单名称都是唯一的,或者使用名称空间存储名称(我不说完全限定,因为持久性可以使命名空间系统与源代码命名空间系统不同;您真正需要的只是一些唯一性)。



当你找到 System.Type 的实例时,你可以找到它的构造函数:

http://msdn.microsoft.com/en-us/library/e687hf0d。 aspx [ ^ ],

http://msdn.microsoft.com/en-us/library/ h70wxday.aspx [ ^ ]。



请注意,您可以找到多个构造函数。哪一个使用?持久性的通常约定是仅使用无参数构造函数。您可以使用公共或非公共构造函数,但通常的假设是您使用任何无参数构造函数。当你找到一个,你可以调用找到的 System.Reflection.ConstructorInfo 的实例,它给你实际的对象或必需的类(我只引用最简单的<$ c形式) $ c>在这里调用:

http: //msdn.microsoft.com/en-us/library/6ycw1y17.aspx [ ^ ]。



就是这样。下一步将决定如何指示成员保持并与这些成员合作。您可以在序列化类本身中要求支持序列化方法,或者,您可以对所有合格成员使用Reflection(数据合同方法)。



现在,让我告诉你,反思很慢。如果对每种类型和每个持久成员反复重复反射,它将允许您以合理的性能存储和恢复仅相对较小的对象图,比如说,千字节到几十千字节,几乎不多。 br />


为了更快地建立基于Reflection的持久性,你需要进入更复杂的模式。我已经提到你需要缓存所涉及的类型。您可以使用由类型名称键入的字典(这将为您提供按名称搜索的O(1)时间复杂度)。但是如何在所有其他情况下避免多余的重复反射?已知的方法是使用 System.Reflection.Emit 。您可以根据每个合同生成一个完整的持久性程序集,并在运行时重用它,或者为每个类型生成一组动态方法;请参阅:

http://msdn.microsoft .com / zh-cn / library / system.reflection.emit.dynamicmethod.aspx [ ^ ]。



你可以结合系统.Reflection.Emit 缓存方法。看起来很难?我知道。这个问题很难解决,尤其是 System.Reflection.Emit 部分,这很难调试,需要非常好地理解CIL和低级别的CLI编程。



-SA


看看这篇文章...... 使用C#2.0中的通用类型将对象序列化和反序列化为XML [ ^ ]

Hi,
I have a common method for Deserialize xml into class object.
I have a method to deserialize XML into class object.
Ihave a query about how to pass common class name to method return type,so i can pass any class name and used in global purpose.
Below are my method-->

public static classsname DeserializeXML(string inputXml)
{
   classsname returnDto;
    string inpXML = inputXml.Replace("", "");
    using (MemoryStream ms = ConvertXmlToStream(inpXML))
    {
        XmlSerializer seralize = new XmlSerializer(typeof(classsname));
        using (XmlTextReader reader = new XmlTextReader(ms))
        {
            returnDto = (classsname)seralize.Deserialize(reader);

            reader.Close();
        }
    }

    return returnDto;
}


In the class name place what i need to keep so it can make global purpose.

Thanks...

解决方案

I must say, this is a very naive attempt to design universal serialization. However, you already got one of the main difficulties: how to deal with polymorphous sets.

I know how to do it for real in fine detail, but explaining it could take a whole really big article. I could simple advice you to look at the implementation of Data Contract (http://msdn.microsoft.com/en-us/library/ms733127.aspx[^]), but, at this time, I don''t know where to find its source code and not sure that Microsoft provides this source code. (The source code for .NET was available before, for learning and debugging purposes only, but it did not include Data Contract; I''m not sure you can find the newer source code at this time; you can try to find out. Also, you can get probably find source code for System.Xml.Serialization.XmlSerializer, http://msdn.microsoft.com/en-us/library/system.xml.serialization.xmlserializer.aspx[^].)

So, I can only focus on one fundamental issue: how to create an instance of the class by the class name taken from a serialization stream.

Basically, this is all done via Reflection.

First, you can take take all the types in some assembly or a set of assemblies:
http://msdn.microsoft.com/en-us/library/system.type.aspx[^],
http://msdn.microsoft.com/en-us/library/system.reflection.assembly.gettypes.aspx[^].

You can scan all the types against the type name and find out the instance of the System.Type with matching name. This is very ineffective, but you can somehow cache all the types found during the first attempt, for future use, so you would not do it repetitively. One problem is: if you use a simple type name, you may face with the resolution between two different types, with different fully-qualified names, but identical simple names. You should either assume that all the simple names are unique, or store names with namespaces (I don''t say "fully-qualified" as persistence can have a namespace system not identical to source code namespace system; all you really need is some uniqueness).

When you found the instance of System.Type, you can find its constructors:
http://msdn.microsoft.com/en-us/library/e687hf0d.aspx[^],
http://msdn.microsoft.com/en-us/library/h70wxday.aspx[^].

Note that you can find more than one constructor. Which one to use? The usual convention for persistence is using only the parameterless constructors. You can use public or non-public constructors, but the usual assumption is that you use any parameterless constructor. When you find one, you can invoke the found instance of System.Reflection.ConstructorInfo which gives you the actual object or required class (I reference only the simplest form of Invoke here):
http://msdn.microsoft.com/en-us/library/6ycw1y17.aspx[^].

That''s it. Next step will be to decide how you indicate the members to persist and working with those members. You can require support of serialization method in the serializeable classes themselves, or, alternatively, you can use Reflection for all qualifying members (Data Contract approach).

Now, let me tell you that Reflection is quite slow. If you repeat reflection over and over for each type and each persisting member, it will allow you to store and restore with reasonable performance only relatively small object graphs, let''s say, kilobytes to some tens of kilobytes, hardly much more.

To make persistence based of Reflection faster, you need to go in for much more complex schema. I already mentioned that you need to cache the types involved. You could use a dictionary keyed by the type names (which will give you O(1) time complexity for search by name). But how to avoid redundant repeated Reflection in all other cases? The known approach is using System.Reflection.Emit. You can either generate a whole persistence assembly, based on each contract, on the fly and reuse it during run-time, or generate a set of Dynamic Methods for each type; please see:
http://msdn.microsoft.com/en-us/library/system.reflection.emit.dynamicmethod.aspx[^].

And you can combine System.Reflection.Emit approaches with caching. Looks difficult? I know. This problem is difficult enough, especially System.Reflection.Emit part, which is hard to debug and requires a very good understanding of CIL and low level of CLI programming.

—SA


Have a look at this article ...Serialize and Deserialize Objects as XML using Generic Types in C# 2.0[^]


这篇关于如何在c#中创建通用方法并传递公共类名?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆