user1174322
user1174322

Reputation: 21

Creating instances and assign properties of a runtime assembly

I need to create a generic solution of creating an instance of a class that is generated from an xsd. For example:

<?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>

when I generate assembly from this xsd runtime it will have classes PS, PSP and PSFX. In this case I know the properties and what to expect so createinstance and getproperties and setvalue will work. I know that a portfolios will have an array of PortfoliosPortfolio.

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);

Now I want to have a generic solution that at can take any xsd (not just the above) and generate an assembly. I have already generated the assemble but now my question how do you dynamically assign properties for the classes that don't know what properties exist in there? What I mean is how do I know that a class is using list of objects of another class when creating generic solution. So instead of hardcoding the classnames and propertynames is there a way to get instances and properties. As you see from the above snippet I am assigning the values from the a dataset to the properties. The plan is to store the values in the database as columnname, attributename and parentnode. So PName attribute in P node will come from column name Pname. I want the design in such a way that there will not be any hardcoding in my code. Can you please suggest me with some examples or design idea.

Sorry please bear with me, please let me know if I am not making sense.

Upvotes: 2

Views: 338

Answers (2)

Bruno Brant
Bruno Brant

Reputation: 8564

Long question deserves a long answer:

I. First, a small credential: I've been working with class / assembly generation for a little while. In fact, you can do this using either CodeDom (preferred method) or IL Emit. But you probably shouldn't.

  • The first argument against this is that that your XML model isn't really that useful. Ok, so you have an XML that you want to turn to a class. To do that, you will somehow turn that XML into code (either C# or VB or even IL), and then compile it in runtime to create a dynamic class. So, why not use code directly instead of XML?
  • The point above has a corollary: if you are specifying the class in design-time, why not compile the class (hence, generating it in compile-time)?

II. Your design driver here is no hard code.

  • First a philosophical analysis: you don't want to hard code code, which is a paradox.
  • It's good practice to minimize hard-coded strings in your source, mostly because (1) those strings are expected to change (2) it might make testing easier. We can extract two things from this definition:
    • You should avoid hard-code strings, not program structure
    • You should only make configurable those things that are expected to change ("dynamic") or unknown to you in compile-time. Database structures are hardly the case.

Now, thinking abstractly, can you avoid hard-code? In your example you have already used some strings that reference the data in the XML file that you are about to process. How will a program work without any information about the data you want to process?

(yep, there is a answer)

...

Answer: when you are just presenting the data, that is, the full data structure is not relevant to the program logic. Examples of this are a text editor. A text editor does not need to know about the data beforehand. You render it as it exists in the file.

In your case, however, the database is the "master" of the data. It's no use trying to separate it from your program.

Upvotes: 1

hbarck
hbarck

Reputation: 2944

Wouldn't it be easier to just parse the XML and not to create an assembly? You could use XmlSchema and its child objects in order to extract all the information you want in your database. You could use a general framework for handling XML documents in order to manipulate the XML output. Or, if you really need the assembly, you could first change the XML, and then deserialize it into an object.

However, if your client code is not supposed to know the CLR types of your assembly at compile time, I think creating the assembly doesn't make much sense in the first place, and you'd be better off creating a general intermediate data format that you can translate to either XML or database columns as needed.

Upvotes: 0

Related Questions