Reputation: 21
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
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.
II. Your design driver here is no hard code.
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
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