Account Options

  1. Sign in
The old Google Groups will be going away soon, but your browser is incompatible with the new version.
Google Groups Home
« Groups Home
Message from discussion Mapping dynamic-component by code with variable number of properties
The group you are posting to is a Usenet group. Messages posted to this group will make your email address visible to anyone on the Internet.
Your reply message has not been sent.
Your post was successful
 
From:
To:
Cc:
Followup To:
Add Cc | Add Followup-to | Edit Subject
Subject:
Validation:
For verification purposes please type the characters you see in the picture below or the numbers you hear by clicking the accessibility icon. Listen and type the numbers you hear
 
Exodus  
View profile  
 More options Apr 10 2012, 5:09 am
From: Exodus <green_sea...@yahoo.se>
Date: Tue, 10 Apr 2012 02:09:32 -0700 (PDT)
Local: Tues, Apr 10 2012 5:09 am
Subject: Re: [nhusers] Re: Mapping dynamic-component by code with variable number of properties

Fabio: Basicly I want to change the mapping of a dynamic component because
the database schema has changed, and do it at runtime. So I want to add
properties to the dynamic component in a for-loop.

Barry: Good find, didn't find that link so I implemented my own version, it
uses a template which I map by code and then I copy the template to my
variable number of attributes. This code works in my limited case, but is
not very general I suspect. Code is below.

modelMapper.Class<TestClass>(c =>
                              {
                                c.Table("TestClass");
                                ...
                                c.Component(x => x.Properties,
                                          new
                                              {
                                                  TEMPLATE = ""
                                              }
                                          , dc =>
                                                {
                                                    dc.Property(arg =>
arg.TEMPLATE);
                                                });
                               });

...
HbmMapping mapping =
modelMapper.CompileMappingForAllExplicitlyAddedEntities();

var dynamicComponentMappingChanger = new
NHibernateDynamicComponentMappingChanger();
dynamicComponentMappingChanger.ClassName = "TestClass";
dynamicComponentMappingChanger.PropertyName = "Properties";
dynamicComponentMappingChanger.AddMappingChange("MyAttribute1", "TEMPLATE");
dynamicComponentMappingChanger.AddMappingChange("MyAttribute2", "TEMPLATE");
dynamicComponentMappingChanger.AddMappingChange("MyAttribute3", "TEMPLATE");
dynamicComponentMappingChanger.ChangeMapping(mapping);

    public class NHibernateDynamicComponentMappingChanger
    {
        public string ClassName { get; set; }
        public string PropertyName { get; set; }
        private Dictionary<string, List<string>> _mappingToChange = new
Dictionary<string, List<string>>();

        /// <summary>
        /// First string is new property name, second string is template
that is already mapped
        /// </summary>
        public void AddMappingChange(string newPropertyName, string
nameOfPropertyToUseAsTemplate)
        {
            _mappingToChange.Add(nameOfPropertyToUseAsTemplate,
newPropertyName);
        }

        public void ChangeMapping(HbmMapping mapping)
        {
            HbmClass hbmClass = mapping.RootClasses.Single(x => x.Name ==
ClassName);
            HbmDynamicComponent dynamicComponent = (HbmDynamicComponent)
hbmClass.Properties.Single(x => x.Name == PropertyName);

            object[] items = dynamicComponent.Items;
            List<object> result = new List<object>();

            foreach(Object o in items)
            {
                HbmProperty hbmProperty = o as HbmProperty;
                if(hbmProperty != null)
                {
                    List<string> list;
                    if(_mappingToChange.TryGetValue(hbmProperty.name, out
list))
                    {
                        foreach(string s in list)
                        {
                            HbmProperty clone =
ObjectCopier.Clone(hbmProperty);
                            clone.name = s;
                            result.Add(clone);
                        }
                    }
                    else
                    {
                        result.Add(hbmProperty);
                    }
                } else
                {
                    result.Add(o);
                }
            }

            dynamicComponent.Items = result.ToArray();
        }
    }

    /// <summary>
    /// Extension functions that makes it possible to have multiple values
for a key in a Dictionary. Dictionary value type should be of type List<>
    /// </summary>
    public static class MultimapExt
    {
        public static void Add<TKey, TValue, TCollection>(
            this IDictionary<TKey, TCollection> dictionary,
            TKey key,
            TValue value
        ) where TCollection : ICollection<TValue>, new()
    {
        TCollection collection;
        if(!dictionary.TryGetValue(key, out collection))
        {
            collection = new TCollection();
            dictionary.Add(key, collection);
        }

        collection.Add(value);
    }

        public static bool Remove<TKey, TValue, TCollection>(
            this IDictionary<TKey, TCollection> dictionary,
            TKey key,
            TValue value
        ) where TCollection : ICollection<TValue>
        {
            TCollection collection;
            if(dictionary.TryGetValue(key, out collection))
            {
                bool removed = collection.Remove(value);

                if(collection.Count == 0)
                    dictionary.Remove(key);

                return removed;
            }

            return false;
        }
    }

    public static class ObjectCopier
    {
        /// <summary>
        /// Perform a deep Copy of the object.
        /// </summary>
        /// <typeparam name="T">The type of object being copied.</typeparam>
        /// <param name="source">The object instance to copy.</param>
        /// <returns>The copied object.</returns>
        public static T Clone<T>(T source)
        {
            if(!typeof(T).IsSerializable)
            {
                throw new ArgumentException("The type must be
serializable.", "source");
            }

            // Don't serialize a null object, simply return the default for
that object
            if(Object.ReferenceEquals(source, null))
            {
                return default(T);
            }

            IFormatter formatter = new BinaryFormatter();
            Stream stream = new MemoryStream();
            using(stream)
            {
                formatter.Serialize(stream, source);
                stream.Seek(0, SeekOrigin.Begin);
                return (T)formatter.Deserialize(stream);
            }
        }
    }    

On Tuesday, April 3, 2012 12:15:18 AM UTC+2, barry schulz wrote:

> I was able to add a dynamic-component and populate that component with the
> correct properties at runtime by using the following link as a starting
> point.

> http://www.junasoftware.com/blog/custom-domain-using-nhibernate-dynam...

> You can still use the by code configuration to setup your dynamic
> component. Notice the anonymous type has no properties (because they are
> not known).

>     mapper.Class<Test>(map =>

>          {
>             map.Component("DynamicAttributes", new { },componentMap =>
>             {
>                componentMap.Access(Accessor.NoSetter); // I do not have a
> setter
>             });

>          });

> After you add your mappings to the Configuration, add the code seen in
> AddMappingExtensions (from the link). You'll have to modify it based on how
> you get your dynamic attribute metadata.

> Example:

>          foreach (var classMapping in config.ClassMappings)
>          {
>             // only do this for the class named Test for testing...
>             if (classMapping.EntityName != "YourCoolNamepsace.Test")
>             {
>                continue;
>             }
>             var componentProperty = classMapping.GetProperty("DynamicAttributes");
>             var component = (Component)componentProperty.Value;

>             //foreach (TODO: get user defined attributes from somewhere)
>             {              

>                // CreateDynamicProperty is hard coded to work with string for testing...

>                component.AddProperty(CreateDynamicProperty("SomeDynamicAttribute", classMapping));

>                component.AddProperty(CreateDynamicProperty(
> "SomeOtherDynamicAttribute", classMapping));             }          }


 
You must Sign in before you can post messages.
To post a message you must first join this group.
Please update your nickname on the subscription settings page before posting.
You do not have the permission required to post.