views:

129

answers:

2

SOME CONTEXT

  • one of my projects requires carrying around some of "metadata" (yes I hate using that word).
  • What the metadata specifically consists of is not important, only that it's more complex than a simple "table" or "list" - you could think of it as a mini-database of information
  • Currently I have this metadata stored in an XML file and have an XSD that defines the schema.
  • I want to package this metadata with my project, currently that means keeping the XML file as a resource
  • However, I have been looking for a more strongly-typed alternative. I am considering moving it from an XML file to C# code - so instead of using XML apis to traverse my metadata, relying on .NET code via reflection on types
  • Besides the strong(er) typing, some useful characteristics I see from using an assembly are for this: (1) I can refactor the "schema" to some extent with tools like Resharper, (2) The metadata can come with code, (3) don't have to rely on any external DB component.

THE QUESTIONS

  • If you have tried something like this, I am curious about what you learned.
  • Was your experience positive?
  • What did you learn?
  • What problems in this approach did you uncover?
  • What are some considerations I should take into account?
  • Would you do this again?

NOTES

  • Am not asking for how to use Reflection - no help is needed there
  • Am fundamentally asking about your experiences and design considerations

UPDATE: INFORMATION ABOUT THE METADATA

Because people are asking I'll try describing the metadata a bit more. I'm trying to abstract a bit - so this will seem a bit artificial.

There are three entities in the model:

  • A set of "groups" - each group has a unique name and several properites (usually int values that represent ID numbers of some kind)
  • Each "group" contains 1 or more "widgets" (never more than 50) - each item has properties like name (therea are multiple names), IDs, and various boolean properties.
  • Each widget contains a one or more "scenarios". Each "scenario" is documentation- a URL to a description of how to use the widget.

Typically I need to run these kinds of "queries"

  • Get the names of all the widgets
  • Get the names of all groups that contain at least one widget where BoolProp1=true
  • Get given the ID of a widget, which group contains that widget

How I was thinking about modelling the entities in the assembly

  • There are 3 classes: Group, Widget, Documentation
  • There are 25 Groups so I will have 25 Group classes - so "FooGroup" will derive from Group, same pattern follows for widgets and documentation
  • Each class will have attributes to account for names, ids, etc.
+1  A: 

It's not clear from your description but it sounds like you have assembly-level metadata that you want to be able to access (as opposed to type-level). You could have a single class in each assembly that implements a common interface, then use reflection to hunt down that class and instantiate it. Then you can hard-code the metadata within.

The problems of course are the benefits that you lose from the XML -- namely that you can't modify the metadata without a new build. But if you're going this direction you probably have already taken that into account.

roufamatic
+1  A: 

I have used and extended Metadata for a large part of my projects, many of them related to describing components, relationships among them, mappings, etc.

(Major categories of using attributes extensively include O/R Mappers, Dependency Injection framework, and Serialization description - specially XML Serialization)

Well, I'm going to ask you to describe a little bit more about the nature of the data you want to embed as resource. Using attributes are naturally good for the type of data that describes your types and type elements, but each usage of attributes is a simple and short one. Attributes (I think) should be very cohesive and somehow independent from each other.

One of the solutions that I want to point you at, is the "XML Serialization" approach. You can keep your current XMLs, and put them into your assemblies as Embedded Resource (which is what you've probably done already) and read the whole XML at once into a strongly-typed hierarchy of objects.

XML Serialization is very very simple to use, much simpler than the typical XML API or even LINQ2XML, in my opinion. It uses Attributes to map class properties to XML elements and XML attributes. Once you've loaded the XML into the objects, you have everything you want in the memory as "typed" data.

Based on what I understand from your description, I think you have a lot of data to be placed on a single class. This means a large and (in my opinion) ugly attribute code above the class. (Unless you can distribute your data among members making each of them small and independent, which is nice.)

I have many positive experiences using XML Serialization for large amount of data. You can arrange data as you want, you get type safety, you get IntelliSence (if you give your XSD to visual studio), and you also get half of the Refactoring. ReSharper (or any other refactoring tool that I know of) don't recognize XML Serialization, so when you refactor your typed classes, it doesn't change the XML itself, but changes all the usage of the data.

If you give me more details on what your data is, I might be able to add something to my answer.

For XML Serialization samples, just Google "XML Serialization" or look it up in MSDN.

UPDATE

I strongly recommend NOT using classes for representing instances of your data. Or even using a class to encapsulate data is against its logical definition.

I guess your best bet would be XML Serialization, provided that you already have your data in XML. You get all the benefits you want, with less code. And you can perform any query on the XML Serializable objects using LINQ2Objects.

A part of your code can look like the following:

[XmlRoot]
public class MyMetadata
{

    [XmlElement]
    public Group[] Groups { get; set; }

}

public class Group
{

    [XmlAttribute]
    public string Name { get; set; }

    [XmlAttribute]
    public int SomeNumber { get; set; }

    [XmlElement]
    public Widget[] Widgets { get; set; }

}

public class Widget
{
    ...
}

You should call new XmlSerializer(typeof(MyMetadata)) to create a serializer, and call its Deserialize method giving it the stream of your XML, and you get a filled instance of MyMetadata class.

Iravanchi