Dynamic data source for ReportingEngine

I’m trying to implement solution which allows passing different data schema to the report template. Those schema’s will change often, therefore defining concrete classes for each isn’t the best way forward. But whenever I pass an anonymous object or a dictionary containing key/value pairs it complains that properties defined in the template cannot be found on the data source object.

Is there a way to pass an object that implements an interface similar to IMailMergeDataSource that would allow dynamic data retrieval?

Alternatively a support for IDictionary<string, object> or ExpandoObject would do?

@patrick6f313,

We are checking your scenario and will get back to you soon.

Best regards,

@patrick6f313,

You can meet this requirement by implementing any of the following options.

  1. In the simplest case, instead of a dictionary, you can pass an array of values and an array of keys as multiple data sources and their names respectively. Then you can access the values by the specified keys normally.

  2. Another way is to pass a dictionary but change template syntax, so that the dictionary to be treated as a dictionary. That is, given that “d” is a dictionary, its “Name” item should be accessed as “d[“Name”]” rather than “d.Name” in a template. Put simply, dictionary items should be accessed in templates in the same way as it would be done in C# code. ExpandoObject implements IDictionary<string, object>, so it is also supported in the same way.

  3. If you need to handle complex objects rather than just strings, numbers, and so on as dictionary values, then there are more complex options as suggested here: Aspose Linq Reporting - #4 by awais.hafeez (just use ReportingEngine.BuildReport instead of DocumentAssembler.AssembleDocument)

  4. Another option is to implement IDataReader or IDataRecord and pass it to the engine.
    Working with Traditional Mail Merge Data Sources.

Hope, this helps.

Best regards,

Thanks for your reply. I’ve looked into the suggested solutions but I still don’t get desired flexibility. Unless I’m missing something.

The main reason for choosing ReportingEngine over MailMerge is simplicity in the template syntax.

Adding placeholders like <<[Name]>> is straightforward to people with little technical experience, who will be maintaining them.

Having an object implementing IDictionary (option 2) could probably address some of the requirements I’ve got but it’s not perfect solution.

The main issues with that are

  • Syntax becomes more convoluted: <<[Name]>> becomes <<[d[“Name”]]>>; adding simple IFs makes it even harder to read.
  • Word often replaces double quotes with special characters - that may be difficult to spot.

@patrick6f313,

I think, you can let user create template as they would normally do, and before calling ReportingEngine.BuildReport method, your application can pre-process such template documents and convert placeholder <<[Name]>> to <<[d[“Name”]]>> to generate desired report using IDictionary. Please refer to the following article:

Best regards,

Try IDictionary …the difference is that Dictionary is concrete implementation while IDictionary is just a contract, abstraction. If IDictionary is a “more generic” type than Dictionary then it makes sense to use the more generic type in declaring variables. It is a good idea to abstract yourself from an implementation, by that I mean programming against an interface rather than a concrete implementation.