2

I wish to give a Person as defined below, the ability to print a vCard out of my system. To provide the user with privacy options, the user can select whether to show/hide certain properties. In it's simplest form, I need to have a separate table that would hold the user's choices.

I was wondering if it was possible to build this configurator table using reflection. As shown in the Person model below, I could decorate properties with a custom attribute, and then using those properties, construct and persist a model that would have a bool property for every decorated Person property.

public class Person
{
    public string UserName { get; set; }
    public string FirstName { get; set; }

    [DisplayOnVCard]
    public string LastName { get; set; }

    [DisplayOnVCard]
    public string Email { get; set; }

    [DisplayOnVCard]
    public string MobilePhone { get; set; }
}

** where [DisplayOnVCard] is a custom attribute.*

At the end of this, I expect a table in the db that would correspond to this:

public class VCardConfigurator
{
    public bool LastName { get; set; }
    public bool Email { get; set; }
    public bool MobilePhone { get; set; }
}

This is just a sample representation of what is actually a huge entity. Which is why I hope to avoid manually mapping a bool field to each optional property.

I believe this problem domain is quite similar to how, for instance, privacy settings work on social networking sites, yes?

While I was typing this, I did ponder upon the possibility that if down the line I was to remove the attribute from one of the properties, what implications that might have. Needs some thought!

Further reading for self:


There is a huge possibility that I am galloping down a totally wrong path! If that is the case, please advice so!

Community
  • 1
  • 1
bPratik
  • 6,894
  • 4
  • 36
  • 67
  • I have not worked extensively with the MS entity framework (mostly because I have built my own), but I was wondering if Ms have any type of dynamic model (like a dictionary where the keys would represent the column name and the value would represent an object that stores the attributes of the column, including its value)? My E.F. can do this! – Matthew Layton Sep 27 '12 at 16:49

1 Answers1

1

#1 Update

I am not sure its possible to add or remove attributes for an instance since attributes are at the class level, but their property values can be changed (Since they are instances).

My suggested solusion

I am not sure what you mean in "I expect a table in the db that would correspond to this", since you can't have a table in the database that contains only the columns of the non-privacy properties for each user.

You will need a dedicated table for this mapping (Lets say 'PrivacyMappings' table), with these columns: UserId, PropertyName, IsPrivate.

When a user is added, all the properties will be added to this table with a default privacy settings (for instance, all properties are non-private by default). You can add the properties by iterating over them and insert them as you said.

You can use the following class in entity framework:

public class PrivacyMapping
{
public int UserId {get;set;}
public string PropertyName {get;set;}
public bool IsPrivate {get;set;}
}

Adding the default privacy settings when a user being added:

// retrieve user model properties.

foreach (property in properties)
{
//iterrate over the user Properties.
context.PrivacyMapping.Add(new PrivacyMapping(user.userId, propertyName, isPrivate);
}

context.SaveChanges()

Now you can take all the user non-private properties by

context.PrivacyMapping.Where(p=>p.UserId == user.id && !IsPrivate).Select(p=>p.PropertyName);

And now you can deal with information any way you want.

For example, you can have a VCardItems class, that receive an user id/object in its c'tor and stores a dictionary of the allowed properties by their names.

public class VCardItems{

private Dictionary<string, object> properties{get;set;}

public VCardItems(User user)
{
// initiate values..
}
        public object this[string name] {
            get 
            { 
                if (properties.ContainsKey(name))
                {
                    return properties[name];
                }

                // A private property.
                return null;

            }
            set 
            {
                properties[name] = value;
            }
        }
    }

There is other options of how to use the data, for example with ActionFilter that in this case sets the private properties to null or storing the non-private data in the HttpContext.Items dictionary, but it really up to you.

First message

Before we get into details, I wonder how you expect to use this class.

If a view (or whatever going to handle it), going to receive have a runtime-generated class for example, how you gonna handle it?

How you gonna know what properties this model has?

Aviran Cohen
  • 5,581
  • 4
  • 48
  • 75
  • I could always iterate over the properties of the model at runtime using something like `foreach(PropertyDescriptor prop in TypeDescriptor.GetProperties(VCardConfigurator))` and then do some hacky mapping of property names, etc. The implementation part of it, I haven't given deep thought to, to be honest. But if I can get a proof of concept running for the above, I could achieve the rest! – bPratik Sep 27 '12 at 16:31