C# mapping data directly to an object - c#

I am creating a library that pulls HTML tables from the web and converts them to objects. I have a ColumnConfigurator object that pre-configures how a specific table is laid out:
config.Column().Text().MapTo(/*Class.TextPropertyName*/); //What I want to be able to do
config.Column().Date().MapTo(/*Class.DatePropertyName*/);
The above code is the general idea of what I want to be able to do in the configuration (note that the first function creates a new column and returns it, and the subsequent methods set the object's configuration), and then when the table is being mapped to I'd like to retrieve the parameter passed into MapTo and have it automatically resolve to the correct property of a given object.
Here's what's confusing me the most: I want to make the main table object generic (ParsingTable<T>) so that theoretically any object can be mapped to. This means that none of the properties are available ahead of time. I'd like to pass the T.Property into the method so it knows how to automap. Is there a way to do this? I've read a small bit about reflection but heard it's bad for performance.

For information on creating a fluent interface (what you are doing for the configuration), see here: creating API that is fluent
For the MapTo method to accept the property name from a generic class, you will end up with something like this:
public class ParsingTable<T>
{
/*** All the other stuff ***/
public static IColumnConfiguration MapTo(this IColumnConfiguration config, Expression<Func<T, object>> property)
{
if (property.Body is MemberExpression)
{
config.Property = (property.Body as MemberExpression).Member as PropertyInfo;
}
else
{
config.Property = (((UnaryExpression)property.Body).Operand as MemberExpression).Member as PropertyInfo;
}
}
}
public interface IColumnConfiguration
{
PropertyInfo Property { get; set; }
}
Then when you are doing the parsing, you would call the PropertyInfo.SetValue() function for each value/column.
You are correct that this will likely be a little on the slower end compared to a direct property set. It depends highly on your situation if this is a big deal or not. The next step would be to compile a lambda expression for each column set if you really want to avoid the SetValue() call.
Note, I took some of the code above from here: http://blog.raffaeu.com/archive/2010/06/26/how-to-write-fluent-interface-with-c-and-lambda.aspx

Related

C# Add custom attribute to a class without modify [duplicate]

Is it possible to add attributes at runtime or to change the value of an attribute at runtime?
This really depends on what exactly you're trying to accomplish.
The System.ComponentModel.TypeDescriptor stuff can be used to add attributes to types, properties and object instances, and it has the limitation that you have to use it to retrieve those properties as well. If you're writing the code that consumes those attributes, and you can live within those limitations, then I'd definitely suggest it.
As far as I know, the PropertyGrid control and the visual studio design surface are the only things in the BCL that consume the TypeDescriptor stuff. In fact, that's how they do about half the things they really need to do.
Attributes are static metadata. Assemblies, modules, types, members, parameters, and return values aren't first-class objects in C# (e.g., the System.Type class is merely a reflected representation of a type). You can get an instance of an attribute for a type and change the properties if they're writable but that won't affect the attribute as it is applied to the type.
You can't. One workaround might be to generate a derived class at runtime and adding the attribute, although this is probably bit of an overkill.
Well, just to be different, I found an article that references using Reflection.Emit to do so.
Here's the link: http://www.codeproject.com/KB/cs/dotnetattributes.aspx , you will also want to look into some of the comments at the bottom of the article, because possible approaches are discussed.
No, it's not.
Attributes are meta-data and stored in binary-form in the compiled assembly (that's also why you can only use simple types in them).
I don't believe so. Even if I'm wrong, the best you can hope for is adding them to an entire Type, never an instance of a Type.
If you need something to be able to added dynamically, c# attributes aren't the way. Look into storing the data in xml. I recently did a project that i started w/ attributes, but eventually moved to serialization w/ xml.
Why do you need to? Attributes give extra information for reflection, but if you externally know which properties you want you don't need them.
You could store meta data externally relatively easily in a database or resource file.
Like mentionned in a comment below by Deczaloth, I think that metadata is fixed at compile time. I achieve it by creating a dynamic object where I override GetType() or use GetCustomType() and writing my own type. Using this then you could...
I tried very hard with System.ComponentModel.TypeDescriptor without success. That does not means it can't work but I would like to see code for that.
In counter part, I wanted to change some Attribute values.
I did 2 functions which work fine for that purpose.
// ************************************************************************
public static void SetObjectPropertyDescription(this Type typeOfObject, string propertyName, string description)
{
PropertyDescriptor pd = TypeDescriptor.GetProperties(typeOfObject)[propertyName];
var att = pd.Attributes[typeof(DescriptionAttribute)] as DescriptionAttribute;
if (att != null)
{
var fieldDescription = att.GetType().GetField("description", BindingFlags.NonPublic | BindingFlags.Instance);
if (fieldDescription != null)
{
fieldDescription.SetValue(att, description);
}
}
}
// ************************************************************************
public static void SetPropertyAttributReadOnly(this Type typeOfObject, string propertyName, bool isReadOnly)
{
PropertyDescriptor pd = TypeDescriptor.GetProperties(typeOfObject)[propertyName];
var att = pd.Attributes[typeof(ReadOnlyAttribute)] as ReadOnlyAttribute;
if (att != null)
{
var fieldDescription = att.GetType().GetField("isReadOnly", BindingFlags.NonPublic | BindingFlags.Instance);
if (fieldDescription != null)
{
fieldDescription.SetValue(att, isReadOnly);
}
}
}
When faced with this situation, yet another solution might be questioning you code design and search for a more object-oriented way. For me, struggling with unpleasant reflection work arounds is the last resort. And my first reaction to this situation would be re-designing the code. Think of the following code, which tries to solve the problem that you have to add an attribute to a third-party class you are using.
class Employee {} // This one is third-party.
And you have code like
var specialEmployee = new Employee();
// Here you need an employee with a special behaviour and want to add an attribute to the employee but you cannot.
The solution might be extracting a class inheriting from the Employee class and decorating it with your attribute:
[SpecialAttribute]
class SpecialEmployee : Employee
{
}
When you create an instance of this new class
var specialEmployee = new SpecialEmployee();
you can distinguish this specialEmployee object from other employee objects. If appropriate, you may want to make this SpecialEmployee a private nested class.

Automapping custom types

I am in the process of setting up nhibernate using fluent nhibernate for a relatively simple setup. Automapping is able to do everything currently fine except for one property on my objects.
I have properties of type MongoDB.Bson.ObjectId. This is simple immutable struct that basically represents a binary ID that can be easily represented in string format as well. These properties cause NHibernate to throw an error saying:
An association from the table PostView refers to an unmapped class:
MongoDB.Bson.ObjectId
This is quite expected of course because I don't expect nhibernate to understand what ObjectId is.
Where I am stuck is that what I want is to be able to tell Nhibernate to map this object type to a string representation in the database. I would like to be able to do this while still using automapping so I don't have to explicitly map all of those objects - what I'd like is to be able to just say "Whenever you find this objecttype use this mapping". I've found mention of NHibernate.UserTypes.IUserType which seems to look like it does what I want but I've found nothing that usefully tells me how to use it.
So to summarise the question:
How can I automatically map a custom data type to a known type for storing in the database (and of course the reverse).
I would prefer not to change my objects to storing the string representation of the object if possible.
You have to write a convention for this type.
Something like this:
public class CustomTypeConvention : IUserTypeConvention
{
public void Accept(IAcceptanceCriteria<IPropertyInspector> criteria)
{
criteria.Expect(x => x.Property.PropertyType == typeof(MyType));
}
public void Apply(IPropertyInstance target)
{
target.CustomType(typeof(string));
}
}
And add this convention to mappings:
mapping.Conventions.Add(new CustomTypeConvention());

Is it possible to add attributes to an existing class using .NET reflection? [duplicate]

Is it possible to add attributes at runtime or to change the value of an attribute at runtime?
This really depends on what exactly you're trying to accomplish.
The System.ComponentModel.TypeDescriptor stuff can be used to add attributes to types, properties and object instances, and it has the limitation that you have to use it to retrieve those properties as well. If you're writing the code that consumes those attributes, and you can live within those limitations, then I'd definitely suggest it.
As far as I know, the PropertyGrid control and the visual studio design surface are the only things in the BCL that consume the TypeDescriptor stuff. In fact, that's how they do about half the things they really need to do.
Attributes are static metadata. Assemblies, modules, types, members, parameters, and return values aren't first-class objects in C# (e.g., the System.Type class is merely a reflected representation of a type). You can get an instance of an attribute for a type and change the properties if they're writable but that won't affect the attribute as it is applied to the type.
You can't. One workaround might be to generate a derived class at runtime and adding the attribute, although this is probably bit of an overkill.
Well, just to be different, I found an article that references using Reflection.Emit to do so.
Here's the link: http://www.codeproject.com/KB/cs/dotnetattributes.aspx , you will also want to look into some of the comments at the bottom of the article, because possible approaches are discussed.
No, it's not.
Attributes are meta-data and stored in binary-form in the compiled assembly (that's also why you can only use simple types in them).
I don't believe so. Even if I'm wrong, the best you can hope for is adding them to an entire Type, never an instance of a Type.
If you need something to be able to added dynamically, c# attributes aren't the way. Look into storing the data in xml. I recently did a project that i started w/ attributes, but eventually moved to serialization w/ xml.
Why do you need to? Attributes give extra information for reflection, but if you externally know which properties you want you don't need them.
You could store meta data externally relatively easily in a database or resource file.
Like mentionned in a comment below by Deczaloth, I think that metadata is fixed at compile time. I achieve it by creating a dynamic object where I override GetType() or use GetCustomType() and writing my own type. Using this then you could...
I tried very hard with System.ComponentModel.TypeDescriptor without success. That does not means it can't work but I would like to see code for that.
In counter part, I wanted to change some Attribute values.
I did 2 functions which work fine for that purpose.
// ************************************************************************
public static void SetObjectPropertyDescription(this Type typeOfObject, string propertyName, string description)
{
PropertyDescriptor pd = TypeDescriptor.GetProperties(typeOfObject)[propertyName];
var att = pd.Attributes[typeof(DescriptionAttribute)] as DescriptionAttribute;
if (att != null)
{
var fieldDescription = att.GetType().GetField("description", BindingFlags.NonPublic | BindingFlags.Instance);
if (fieldDescription != null)
{
fieldDescription.SetValue(att, description);
}
}
}
// ************************************************************************
public static void SetPropertyAttributReadOnly(this Type typeOfObject, string propertyName, bool isReadOnly)
{
PropertyDescriptor pd = TypeDescriptor.GetProperties(typeOfObject)[propertyName];
var att = pd.Attributes[typeof(ReadOnlyAttribute)] as ReadOnlyAttribute;
if (att != null)
{
var fieldDescription = att.GetType().GetField("isReadOnly", BindingFlags.NonPublic | BindingFlags.Instance);
if (fieldDescription != null)
{
fieldDescription.SetValue(att, isReadOnly);
}
}
}
When faced with this situation, yet another solution might be questioning you code design and search for a more object-oriented way. For me, struggling with unpleasant reflection work arounds is the last resort. And my first reaction to this situation would be re-designing the code. Think of the following code, which tries to solve the problem that you have to add an attribute to a third-party class you are using.
class Employee {} // This one is third-party.
And you have code like
var specialEmployee = new Employee();
// Here you need an employee with a special behaviour and want to add an attribute to the employee but you cannot.
The solution might be extracting a class inheriting from the Employee class and decorating it with your attribute:
[SpecialAttribute]
class SpecialEmployee : Employee
{
}
When you create an instance of this new class
var specialEmployee = new SpecialEmployee();
you can distinguish this specialEmployee object from other employee objects. If appropriate, you may want to make this SpecialEmployee a private nested class.

Setting Values on a derived class from the base class constructor using Reflection

I have two classes like this:
public abstract class MyBase
{
protected MyBase(){
Initialize();
}
protected IDictionary<string,string> _data;
private void Initialize() {
// Use Reflection to get all properties
// of the derived class (e.g., call new MyDerived() then
// I want to know the names "Hello" and "ID" here
var data = GetDataFromBackend(propertyNamesFromDerived);
_data = data;
}
}
public class MyConcrete : MyBase
{
public MyConcrete(){
// Possibly use Reflection here
Hello = _data["Hello"];
ID = new Guid(data["ID"]);
}
public string Hello {get;set;}
public Guid ID {get; set;}
}
As you see, I want the constructor of my base class to know about the properties of the derived class I'm instantiating.
Now, this seems like a huge and big code smell, so let me give some more background about my intentions, maybe there is a better way.
I have a backend system that stores Key/Value Pairs, essentially a Dictionary<string,string>. I want to abstract away working with this backend system in a way where people can create classes whose properties are Keys into the backend system. When they construct this object, it will automatically load the data from that system and initialize all the variables to it.
In other words, I've just reinvented serialization, except that I don't control the backend system and just rather make working with it really painless. I don't want callers to have to call Initialize() after constructing the object, because in 100% of the cases you have to initalize it after constructing.
I don't want to move the initialize code into the Derived Classes, except for string-to-business-object conversion.
Would I have to use a Factory? Or is it considered safe to look at the property names of a derived class in a base constructor? (Don't care about their values and that they aren't initialized, just need the names).
Or is there a better way altogether to provide a facade between a Dictionary of strings and a concrete business object?
Edit: This is .net 3.5, so no System.Dynamic which would make this trivial :(
Edit 2: After looking at the Answers and thinking through this some more, I guess my question really boils down to this now: Is calling GetType().GetProperties() from a base constructor in order to get the Names of Properties and if they are decorated with a certain Attribute safe?
Wait, let's stop here for a second and do this properly. It shouldn't be MyBase's responsibility to do this.
So you write a class that manages getting stuff out of the backend for you, and you write a method on that class that is something like
T Get<T>() where T : new()
and you make Get responsible for reading the dictionary out of the backend and using reflection to populate an instance of T. Thus, you say
var concrete = foo.Get<MyConcrete>();
This isn't hard, and it's the right way to do it.
Incidentally, the code for Get is going to look something like
T t = new T();
var properties = typeof(T).GetProperties();
foreach(var property in properties) {
property.SetValue(t, dictionary[property.Name], null);
}
return t;
where dictionary is your loaded up key/value pairs. It turns out there are more optimal ways to do this, but unless it's a bottleneck I wouldn't worry about it.
The better way to do this would be to make the classes use the dictionary directly:
public string Hello {
get { return (string)base.data["Hello"]; }
set { base.data["Hello"] = value; }
}
You may want to call TryGetValue in the getter so that you can return a default value if the key isn't there. (You should probably do that in a separate method in the base class)
You can make a code snippet to make the properties easier to create.
If you don't want to do it this way, you can call GetType().GetProperties() to get PropertyInfo objects for the properties in your class, then call SetValue(this, value).
This will be slow; there are various tricks you can use to speed it up using expression trees, CreateDelegate, or IL generation.
Maybe try the Template method pattern
Have you considered using an ExpandoObject? With it you can dynamically add properties and inspect them (when serializing for example).
I'm not sure if it's what you really should do, but here's what you asked for (put this in Initialize, and you'll get a list of the derived property names):
var derivedProps = this.GetType().GetProperties();
var propNames = new List<string>(derivedProps.Select(x => x.Name));
From there, using the PropertyInfos in derivedProps, you can set the properties.
You can't really safely do anything to those properties in the base-class constructor anyway as some derived constructor may reset them anyway. You're much better off doing a two-phased load (e.g. call Initialize explicitly)

How would you improve this shallow copying class?

I've written a class with a single static method that copies property values from one object to another. It doesn't care what type each object is, only that they have identical properties. It does what I need, so I'm not engineering it further, but what improvements would you make?
Here's the code:
public class ShallowCopy
{
public static void Copy<From, To>(From from, To to)
where To : class
where From : class
{
Type toType = to.GetType();
foreach (var propertyInfo in from.GetType().GetProperties(BindingFlags.GetProperty | BindingFlags.Public | BindingFlags.Instance))
{
toType.GetProperty(propertyInfo.Name).SetValue(to, propertyInfo.GetValue(from, null), null);
}
}
}
I'm using it as follows:
EmployeeDTO dto = GetEmployeeDTO();
Employee employee = new Employee();
ShallowCopy.Copy(dto, employee);
Are your DTOs serializable? I would expect so, in which case:
MemberInfo[] sm = FormatterServices.GetSerializableMembers(typeof(From));
object[] data = FormatterServices.GetObjectData(from, sm);
FormatterServices.PopulateObjectMembers(to, sm, data);
But note that I don't really agree with this general approach. I would prefer a strong contract for copying on your DTOs that each DTO implements.
Change your type parameter names to comply with naming conventions, e.g. TFrom and TTo, or TSource and TDest (or TDestination).
Do most of your work in a generic type instead of in just a generic method. That allows you to cache the properties, as well as allowing type inference. Type inference is important on the "TFrom" parameter, as it will allow anonymous types to be used.
You could potentially make it blindingly fast by dynamically generating code to do the property copying and keeping it in a delegate which is valid for the "from" type. Or potentially generate it for every from/to pair, which would mean the actual copying wouldn't need to use reflection at all! (Preparing the code would be a one-time hit per pair of types, but hopefully you wouldn't have too many pairs.)
A new method that created a new instance of To and called the Copy() method before returning might be useful.
Like this:
public static To Create<From, To>(From from)
where To : class, new()
where From : class
{
var to = new To();
Copy(from, to);
return to;
}
Decide what you want to do if passed objects of types that share some properties but not all. Check for the existence of the property in the From object in the To object before trying to set it's value. Do the "right thing" when you come to a property that doesn't exist. If all of the public properties need to be identical, then you will need to check if you've set all of them on the To object and handle the case where you haven't appropriately.
I'd also suggest that you may want to use attributes to decorate the properties that need to be copied and ignore others. This would allow you to go back and forth between the two different objects more easily and continue to maintain some public properties that are derived rather than stored on your business object.

Categories

Resources