Using DescriptionAttribute in Domain Entities - c#

I am currently developing a system that needs to expose some of its metadata/documentation at runtime. I know there are methods of using XML Comments and bringing that data back into the app via homegrown Reflection extension methods.
I feel it might be easier to use the description attribute from the System.ComponentModel namespace (but located in System assembly). This way I and other developers would be able use regular reflection to get the Description of fields. I much rather use this than using a custom attribute. What are the downsides to this approach?
Example:
public Customer
{
public int Id { get; set; }
[Description("The common friendly name used for the customer.")]
public string Name { get; set; }
[Description("The name used for this customer in the existing Oracle ERP system.")]
public string ErpName { get; set; }
}

I am doing the exact same thing (with ERP software no less!) and have encountered no drawbacks. One thing you may consider a drawback in your situation depending on your architecture is that many documentation tools are directly or indirectly based on XML comments. They will likely not be able to pick up description attributes. But in our architecture, the Description attribute code is not actually the master/source of the documentation. We have a database of MetaData that defines and describes every property. We can generate XML comments and Description attributes from that same source. Actually in our case, we do not generate the XML comments at all, but instead directly generate the XML file that would normally be generated by the XML comments directly. That's the file used by the documentation tools we use. You could probably write a simple utility to extract the description attributes into a similar XML file if you want to use documentation tools that rely on the xml file output by xml comments, if it can't accept the Describiton attribute directly.

Related

Exporting EF Entity to Excel/PDF and How to Exclude Attributes without violating SRP?

I am working with Entity Framework as my ORM for a project at work, and I need to be able to write only some of the values of each entity to an existing Excel template.
The data is required to be formatted as Excel Tables so that the end user can reference the information by using formulas like "=AVG(People_Table[Age])". (note, this is just a contrived example for a simplicity). There is also a requirement to export the values to PDF as well.
I've decide that reflection is the way to go to export the information in the least painful manner possible. The problem now, however, is I want to exclude certain properties from being written to the spreadsheet. And I also might want to write the properties in a certain order and specify a display format.
One way I could do this is with defining specific Data Attributes on the properties. I liked this answer on ignoring specific attributes: Exclude property from getType().GetProperties(). So a possible solution could be:
// class I want to export
public class PersonEntity {
[SkipAttribute] // per solution in the referenced answer
public int PersonId { get; set; }
[SkipAttribute]
public int ForeignKeyId { get; set; }
[Display(Order = 3)]
public int Age { get; set; }
[Display(Name="First Name", Order = 1)]
public string FirstName { get; set; }
[Display(Name="Last Name", Order = 2)]
public string LastName { get; set; }
/* additional properties remove for brevity */
}
The Problem I see with the above solution is that this entity class is now doing two things: One, proving a mapping between EF and the Database which is it's primary function, and two providing information on how to consume the class for exporting to Excel. I see this as getting messy and leading to confusion because it (possibly?) violates SRP. And, also, I only need the SkipAttribute when exporting to Excel, most of the time I will just ignore this attribute.
An alternative solution that I see could be to create a separate set of classes that only contains the needed properties and to use this for exporting to Excel, and then using a tool like AutoMapper to map from EF Person to this class.
So, the export class would be:
public class PersonExportModel {
[Display(Name="First Name")]
public string FirstName { get; set; }
[Display(Name="Last Name")]
public string LastName { get; set; }
public int Age { get; set; }
/* additional properties removed for brevity */
}
And I would just use reflection to dump the values out to the specified format using ClosedXML or a PDF rendering library like ITextSharp.
Concern with the above solution is that this is going to end up with a lot of extra code just to ignore a few unwanted properties (mostly PK's, FK's, and some complex relationship properties). I am also at the issue any updates to the EF class, like removing a property, will require me to also go through the other classes and remove the corresponding properties. But I like this solution because there is less confusion to me about what data is needed for exporting to Excel.
So I'm stuck between either bloating my EF class to tell how it should be exported or creating other ExportModels that are tightly coupled to the EF class and would be a pain to update if the underlying model changes. And the whole mapping between classes is a real pain, which can be alleviated with AutoMapper. This comes with, however, it's own set of problems with obfuscated mapping and performance penalties. I could live with these "problems" if it means I do not have to manually map between the two classes.
I've thought about farming the work out to a SSRS but I need to ability to write the data to specific existing workbooks which I understand is not possible. I'd also need the ability to create named tables which also I understand is not possible out of the box with SSRS. I'd also need to create two reports because the Excel output would look much different than the PDF format. So even the SSRS would cause a lot of extra work.
Any suggestions on which solution might be best, or perhaps an alternative approach? The requirement of this project is in flux so I'm looking for a solution that will be as painless as possible to updates.

Add property to POCO class at runtime

I selected ServiceStack OrmLite for my project which is a pure Data-Oriented application. I am willing to allow the end user to create his own Object Types defined in an XML format that will be used to generate classes at runtime using CodeDOM.
I will be also defining some "system" objects required by the application (i.e. User) but I cannot foresee all the properties the end user will use and therefore I am looking for a way to allow extending the classes I create in design time. Sample bellow
public class User
{
public Guid Uid { get; set; }
public String Username { get; set; }
public String Password { get; set; }
}
The end user wants to have an Email and an Address. He should be able to add the 2 properties to the upper class and the whole class will be (which still can be used by OrmLite, since it allows overwriting :
public class User
{
public Guid Uid { get; set; }
public String Username { get; set; }
public String Password { get; set; }
public String Email{ get; set; }
public String Address { get; set; }
}
I know that there might be a risk of doing so to crash the system (if the class is already instantiated) so I am looking for the best way to avoid this issue and mimic the need I have.
It seems that there are two parts to what you're doing here. You need to create types dynamically to support the additional properties. You also need to ensure that you never end up with duplicate types in your AppDomain, i.e. two different definitions of User.
Runtime type generation
The various suggestions already given handle how to create the types. In one project, we had something similar. We created a base class that had the core properties and a dictionary to store the 'extension' properties. Then we used Reflection.Emit to create a derived type that had the desired properties. Each property definition simply read from or wrote to the dictionary in the base class. Since Reflection.Emit entails writing low-level IL code, it seems complex at first. We wrote some sample derived classes in another class library and compiled them. These were examples of what we'd actually need to achieve at runtime. Then we used ildasm.exe to see what code the compiler produced. This made it quite easy to work out how we could generate the same code at runtime.
Avoiding namespace collisions
Your second challenge is to avoid having duplicate type names. We appended a guid (with invalid characters removed) to the name of each generated type to make sure this never happened. Easy fix, though I don't know whether you could get away with that with your ORM.
If this is server code, you also need to consider the fact that assemblies are never unloaded in .NET. So if you're repeatedly generating new types at runtime, your process will continue to grow. The same will happen in client code, but this may be less of an issue if you don't expect the process to run for an extended period of time.
I said assemblies are not unloaded; however, you can unload an entire AppDomain. So if this is server code you could have the entire operation run in its own appdomain, then tear it down afterwards to ensure that the dynamically created types are unloaded.
Check out the ExpandoObject, which provides dynamic language support for doing something like this. You can use it to add additional properties to your POCO's at runtime. Here's a link on using .NET's DLR features: http://msdn.microsoft.com/en-us/library/system.dynamic.expandoobject%28v=vs.100%29.aspx
Why not use a key value pair for all its properties, or at least the dynamic ones?
http://msdn.microsoft.com/en-us/library/system.collections.hashtable.aspx
You can do it the way you're describing with Reflection but it will take a performance hit, this way will allow removal of properties also.
The project I'm currently working on has a similar requirement. We have a system already in production and had a client request addition fields.
We solved this by simply adding a CustomFields property to our model.
public class Model: IHasId<Guid>
{
[PrimaryKey]
[Index(Unique = true)]
public Guid Id { get; set; }
// Other Fields...
/// <summary>
/// A store of extra fields not required by the data model.
/// </summary>
public Dictionary<string, object> CustomFields { get; set; }
}
We've been using this for a few weeks with no issues.
An additional benefit we found from this was that each row could have its own custom fields so we could handle them on a per record basis instead of requiring them for every record.

Generic Windows Form Template

I am creating a generic Windows Form that accepts T and uses reflection with custom attributes to create labels and input controls at run-time.
Example:
class GenericForm<T>: Form where T : ICloneable<T>
{
}
Here's a link to a previous question for the form code: SO Question.
This form could accept the following entity class as an example:
class Vehicle: ICloneable<Vehicle>
{
public int Id { get; set; }
public int Name { get; set; }
public int Description { get; set; }
}
As you could imagine, the magic behind the form would use reflection to determine data types, validation criteria, preferred control types to use, etc.
Rather than re-inventing the wheel, I thought it would be worth asking on SO if anyone knows of such frameworks. Needless to say, I'm looking for something simple rather than a bulky framework.
eXpressApp Framework (XAF) can generate UI on the fly. In a simple case, a programmer will create business entities only, and will not care of UI at all.
As far as I know, there are no frameworks that generate the UI code at runtime. There are plenty of tools (code-generators) that do this before. But you wouldn't have the advantage of "only" changing the code - you'd had an extra step where you would need to start the code generator.
If you really want to create the UI information at runtime - I'd generate Attributes for your properties, that would tell your UI generator how to deal with this property (if no Attribute is given - have a default for your datatypes). It's a lot of coding but could save you time for small to medium projects in the future.
Another thing you could do is to externalize your UI information into an XML file and have a generator for that one. There's actually a framework that does that - have a look at the re-motion framework. I don't know if the part of the UI is free but it has some functionality (i.e. mixins) that could help you fulfilling your task.

How to use XmlAttributeOverrides with WCF

I have a WCF service using basicHttpBinding. On a service method I have a class that is returned, for this class I need to dynamically / programmatically exclude properties and change property names for the XML. This needs to be done both in the WSDL and when the service method is called.
I have searched for the best solution and it seems that I will need to (1) use the XmlAttributeOverrides with the XmlSerializer or (2) implement the IXmlSerializable on the class that needs to be customized. Or there may be a better solution altogether. I know that Property Name + "Specified" can be added to the class and then those properties can be excluded. However, this does not exclude in the WSDL and this doesn't solve the property renaming issue.
Why do I want this? Because of globalization and customization of our application. There are many properties that are built into our application that may be renamed or hidden entirely from users of the application.
After MUCH research I the best option is to swap out the WCF serializer with my own custom serializer. However, I never found good examples of how to do this for a custom class that would use the XmlSerializer. Also I'm not sure how I would pass in the XmlAttributeOverrides for a specific class.
Also, this might not be the case for others who want this same functionality but in my application I only need to initialize the values once for the lifetime of the app. Too bad C# doesn't allow static readonly variables to be used with attributes.
Here is an simple example of a class:
public Customer
{
public string Address1
{
get;
set;
}
public string Address2
{
get;
set;
}
public string Zipcode
{
get;
set;
}
}
In this example I would like to for certain installations of the application use PostalCode instead of Zipcode and hide the Address2 property.
Your help is very much appreciated.
Thanks,
Tyler
There are many properties that are built into our application that may be renamed or hidden entirely from users of the application.
A standard approach is to create a special Data Transfer Object (DTO). Or several.
I know this seems like a bit of a cop out, but since your object property names are dynamic why not just use property bagging instead of doing this XMLSerializer shuffle?

Alternative to XML Serialization for Configuration

Currently, we use a giant configuration object that is serialized to/from XML. This has worked fine for the most part, but we are finding that in the case of power loss and application crashes, that the file could be left in a state that renders it unable to deserialize properly, effectively corrupting the configuration information.
I would like to use the built-in app.config, but it doesn't seem to easily support custom classes. For example, with XML serialization, I can easily serialize a generic list<ComplexClass> with no extra code. It just works. It seems that when using app.config, you have to provide a ton of information and custom classes for this to work. Plus, most of the "custom configuration" tutorials are from circa-2007 and may be outdated for all I know. Does anyone have information to the latest way to do this in .NET 4.0?
In addition, when a problem occurs in the application, 9/10 times it is because of an improper configuration. App.config likes to store user-changeable settings in a very inaccessible location for users who aren't familiar with hidden directories and such. Is there any way to have a single location to store the config file, which the user can easily email us when a problem occurs?
Or, is all this easier than I remember it being in early 2.0 days? Any links or quick examples of how to easily do custom app.config information would be great.
As a further example, this is a pared-down version of one of the types of objects I want to serialize as List<Alarm>, as the amount of Alarms can vary or be empty. Is there an analogous way to store something like this in app.config?
[Serializable]
public class Alarm
{
[Serializable]
public class AlarmSetting
{
public enum AlarmVariables { Concentration, RSquared }
public enum AlarmComparisons { LessThan, GreaterThan }
[Description("Which entity is being alarmed on.")]
public AlarmVariables Variable { get; set; }
[Description("Method of comparing the entity to the setpoint.")]
public AlarmComparisons Comparator { get; set; }
[Description("Value at which to alarm.")]
public Double Setpoint { get; set; }
}
public String Name { get; set; }
public Boolean Enabled { get; set; }
public String Parameter { get; set; }
public List<AlarmSetting> AlarmSettings { get; set; }
public System.Drawing.Color RowColor { get; set; }
}
I would suggest moving away from any sort of config file and instead use some type of local database such as sqlite or sql server express which is much more resilient to app crashes.
IMHO, config settings shouldn't be a default container for user settings. To me a config file is there to make sure the app runs in the given environment. For example, defining connection strings or polling rates or things of that nature.
User settings, especially ones that change often, need a better storage mechanism such as a local database. Unless, of course, it's a client/server application. In which case those settings should be up at the server itself and only persisted locally if the app has to work in a disconnected state.
The example you gave, one of configuring what appears to be one or more alarms is a perfect example of something that belongs in a database table.
I have been using XML serialization, similar to what you are describing, for many years on a number of different projects. Unless you want to bite off SQL for configuration, this seems to be the best solution.
IMHO, the app.config mechanism is not any better than straight XML serialization. It is actually more difficult to access this configuration from a number of different projects. If you are only saving transient state (user options etc) from a WinForms application, then application settings can be convenient for simple data types.
It seems to me like you have another issue that is causing the corruption. I rarely get file corruption with these XML files. Whenever I do, it is related to an exception that is thrown during serialization, not due to application crash etc. If you want to double check this, you might want to serialize to memory stream and then dump the memory stream to disk. You can actually serialize, deserialize the stream to make sure it's valid prior to dumping the file to disk.
Unless you are writing this file a lot I would be skeptical that the file corruption is due to power outages.
Unless you can track down the source of the error, you're only just guessing that it has anything to do with Xml files. It's entirely possible the built-in XmlSerializer is failing .. e.g. you may have a circular reference somewhere, but it's hard to comment unless you know what your error is.
Sometimes using the built-in Xml Serializer isn't the best choice, and when objects get complex, it can be better to perform the serialization and deserialization yourself. You'll have more control and be able to more accurately determine / recover from bad file data.
XDocument doc = new XDocument(
new XElement("attachments",
new XElement("directory", attachmentDirectory),
new XElement("attachment-list",
from attached in attachedFiles
select new XElement("file",
new XAttribute("name", attached.FileName),
new XAttribute("size", attached.FileSize))
)
)
);
Other than that, configuration files are for configuration, not program data. The difference is configuration data shouldn't change often, and normally isn't too directly editable from users. In a winforms app, you don't share data between users in a configuration file. If you do, then you should consider if your app is really a database application.
Since we have made a decision to abdicate from Microsoft Configuration System in 2007
we have not regretted for a second.
Take a look at this:
http://blog.aumcode.com/2013/08/aum-configuration-as-facilitated-by-nfx.html

Categories

Resources