C# 创建运行时程序集的实例并指定其属性

C# 创建运行时程序集的实例并指定其属性,c#,system.reflection,C#,System.reflection,我需要创建一个通用解决方案,创建从xsd生成的类的实例。例如: <?xml version="1.0" encoding="utf-8"?> <xs:schema attributeFormDefault="unqualified" elementFormDefault="qualified" xmlns:xs="http://www.w3.org/2001/XMLSchema"> <xs:element name="PS"> <xs:com

我需要创建一个通用解决方案,创建从xsd生成的类的实例。例如:

<?xml version="1.0" encoding="utf-8"?>
<xs:schema attributeFormDefault="unqualified" elementFormDefault="qualified" xmlns:xs="http://www.w3.org/2001/XMLSchema">
  <xs:element name="PS">
    <xs:complexType>
      <xs:sequence>
        <xs:element name="P" maxOccurs="unbounded">
          <xs:complexType>
            <xs:sequence>
              <xs:element name="FXs" maxOccurs="1" minOccurs="0">
                <xs:complexType>
                  <xs:sequence>
                    <xs:element maxOccurs="unbounded" name="FX" minOccurs="1">
                      <xs:complexType>
                        <xs:attribute name="asOfDate" type="xs:date" use="required" />
                        <xs:attribute name="currency" type="xs:string" use="required" />
                        <xs:attribute name="rate" type="xs:decimal" use="required" />
                      </xs:complexType>
                    </xs:element>
                  </xs:sequence>
                </xs:complexType>
              </xs:element>
 </xs:sequence>
            <xs:attribute name="PName" type="xs:string" />
            <xs:attribute name="currency" type="xs:string" />
          </xs:complexType>
        </xs:element>
      </xs:sequence>
    </xs:complexType>
  </xs:element>
</xs:schema>
现在我想要一个通用的解决方案,它可以接受任何xsd(不仅仅是上面提到的)并生成一个程序集。我已经生成了汇编,但现在我的问题是,如何为不知道其中存在哪些属性的类动态分配属性?我的意思是,在创建泛型解决方案时,如何知道一个类正在使用另一个类的对象列表。因此,有一种方法可以获取实例和属性,而不是硬编码类名和属性名称。正如您从上面的代码片段中看到的,我正在将数据集中的值分配给属性。计划是将这些值作为columnname、attributename和parentnode存储在数据库中。 所以P节点中的PName属性将来自列名PName。我希望这样的设计,将不会有任何硬编码在我的代码。你能给我推荐一些例子或设计理念吗


对不起,请原谅我,如果我讲不通,请告诉我。

只解析XML而不创建程序集不是更容易吗?您可以使用XmlSchema及其子对象来提取数据库中所需的所有信息。您可以使用处理XML文档的通用框架来操作XML输出。或者,如果确实需要程序集,可以先更改XML,然后将其反序列化为对象


但是,如果您的客户机代码在编译时不应该知道程序集的CLR类型,那么我认为创建程序集首先没有多大意义,您最好创建一种通用的中间数据格式,可以根据需要转换为XML或数据库列。

长问题需要一个长答案:

I.首先,一个小证明:我已经在处理类/程序集生成有一段时间了。事实上,您可以使用(首选方法)或。但你可能不应该

  • 反对这一点的第一个论点是,您的XML模型实际上没有那么有用。好的,您有一个XML,您想将其转换为一个类。为此,您将以某种方式将XML转换为代码(C#或VB甚至IL),然后在运行时编译它以创建动态类。那么,为什么不直接使用代码而不是XML呢
  • 上面这一点有一个推论:如果在设计时指定类,为什么不编译该类(因此,在编译时生成它)

II.这里的设计驱动程序是没有硬代码的

  • 首先是哲学分析:你不想硬编码,这是一个悖论
  • 将源代码中的硬编码字符串最小化是一种很好的做法,主要是因为(1)这些字符串预期会发生变化(2)这可能会使测试更容易。我们可以从这个定义中提取两件事:
    • 您应该避免硬代码字符串,而不是程序结构
    • 您应该只对那些在编译时预期会更改(“动态”)或未知的内容进行配置。数据库结构绝非如此
现在,抽象地思考一下,你能避免硬代码吗?在您的示例中,您已经使用了一些字符串,这些字符串引用了将要处理的XML文件中的数据。如果没有任何有关要处理的数据的信息,程序将如何工作

(是的,有答案)

答:当您只是呈现数据时,即完整的数据结构与程序逻辑无关。例如文本编辑器。文本编辑器不需要事先了解数据。可以按文件中的存在方式渲染它

但是,在您的情况下,数据库是数据的“主控”。试图将它与您的程序分离是没有用的

case "PS":
                                    if (p== null)
                                        p= myAssembly.CreateInstance(cls.FullName);
                                    break;

                                case "PSP":
                                    myClass = myAssembly.CreateInstance(cls.FullName);
                                    myClass.GetType().GetProperty("PName").SetValue(myClass, dt.Rows[0]["PortfolioName"].ToString(), null);
                                    myClass.GetType().GetProperty("currency").SetValue(myClass, dt.Rows[0]["Currency"].ToString(), null);
                                    if (myClasses == null)
                                        myClasses = Array.CreateInstance(myClass.GetType(), deals.Count());
                                    myClasses.SetValue(myClass, l);
                                    l++;
                                    portfolio.GetType().GetProperty("P").SetValue(p, myClasses, null);