17 using System.Collections.Generic;
19 using System.Reflection;
20 using System.Runtime.CompilerServices;
22 using erminas.SmartAPI.CMS.Project;
23 using erminas.SmartAPI.Exceptions;
25 namespace erminas.SmartAPI.CMS
29 void AssignAllLanguageIndependentRedDotAttributes<T>(T source, T target);
30 void AssignAllRedDotAttributesForLanguage<T>(T source, T target,
string language) where T :
IProjectObject;
35 public void AssignAllLanguageIndependentRedDotAttributes<T>(T source, T target)
38 typeof (T).GetProperties(BindingFlags.Instance | BindingFlags.Public | BindingFlags.FlattenHierarchy);
39 foreach (var curProperty
in properties)
41 if (!curProperty.CanRead || !curProperty.CanWrite)
46 var attribute = GetRedDotAttribute(curProperty);
47 if (attribute == null || attribute.IsReadOnly)
53 CopyValue(source, target, curProperty);
56 throw new AttributeChangeException(curProperty.Name, e);
61 public void AssignAllRedDotAttributesForLanguage<T>(T source, T target,
string language)
65 typeof (T).GetProperties(BindingFlags.Instance | BindingFlags.Public | BindingFlags.FlattenHierarchy);
66 foreach (var curProperty
in properties)
68 if (!curProperty.CanRead)
73 var attribute = GetRedDotAttribute(curProperty);
74 if (attribute == null || attribute.IsReadOnly)
80 CopyValueForLanguage(source, target, curProperty, language);
83 throw new AttributeChangeException(curProperty.Name, e);
88 private static void CopyLanguageDependendValue<T>(T source, T target, PropertyInfo propertyInfo,
string language)
91 var sourceValue = propertyInfo.GetValue(source, null);
92 var targetValue = propertyInfo.GetValue(target, null);
94 var sourceLanguageIndexer = GetLanguageIndexer(sourceValue);
95 var targetLanguageIndexer = GetLanguageIndexer(targetValue);
97 var value = sourceLanguageIndexer.GetValue(sourceLanguageIndexer,
new object[] {language});
99 targetLanguageIndexer.SetValue(targetLanguageIndexer, value,
new object[] {language});
102 private static void CopyValue<T>(T source, T target, PropertyInfo curProperty)
104 const bool DONT_SHOW_NON_PUBLIC_ACCESSORS =
false;
105 var getMethod = curProperty.GetGetMethod(DONT_SHOW_NON_PUBLIC_ACCESSORS);
106 var setMethod = curProperty.GetSetMethod(DONT_SHOW_NON_PUBLIC_ACCESSORS);
108 var value = getMethod.Invoke(source,
new object[0]);
110 setMethod.Invoke(target,
new[] {value});
113 private static void CopyValueForLanguage<T>(T source, T target, PropertyInfo propertyInfo,
string language)
116 if (typeof (ILanguageDependentValueBase).IsAssignableFrom(propertyInfo.PropertyType))
118 CopyLanguageDependendValue(source, target, propertyInfo, language);
121 CopyValue(source, target, propertyInfo);
124 private static PropertyInfo GetLanguageIndexer(
object @
object)
126 return @
object.GetType().GetProperties(BindingFlags.Instance | BindingFlags.Public).First(info =>
128 var param = info.GetIndexParameters().FirstOrDefault();
129 return param != null && param.ParameterType == typeof (
string);
133 private static RedDotAttribute GetRedDotAttribute(PropertyInfo curProperty)
135 const bool USE_INHERITED =
true;
137 curProperty.GetCustomAttributes(typeof (RedDotAttribute), USE_INHERITED).Cast<RedDotAttribute>();
138 return attributes.FirstOrDefault();
142 internal class AttributeChangeException : Exception
144 private readonly
string _attributeName;
146 public AttributeChangeException(
string attributeName, Exception exception)
147 : base(string.Format(
"Could not change attribute {0}", attributeName), exception)
149 _attributeName = attributeName;
152 public string AttributeName
154 get {
return _attributeName; }
158 internal abstract class AbstractAttributeContainer : ISessionObject
160 private readonly ISession _session;
161 protected XmlReadWriteWrapper _readWriteWrapper;
162 protected XmlElement _xmlElement;
164 internal AbstractAttributeContainer(ISession session)
169 internal XmlReadWriteWrapper XmlReadWriteWrapper {
get {
return _readWriteWrapper; } }
171 internal AbstractAttributeContainer(ISession session, XmlElement xmlElement)
174 if (xmlElement == null)
178 _xmlElement = xmlElement;
179 _readWriteWrapper =
new XmlReadWriteWrapper(_xmlElement,
new Dictionary<string, string>());
182 public virtual ISession Session
184 get {
return _session; }
187 public virtual XmlElement XmlElement
189 get {
return _xmlElement; }
190 protected internal set
193 _readWriteWrapper =
new XmlReadWriteWrapper(_xmlElement,
new Dictionary<string, string>());
197 protected virtual T GetAttributeValue<T>([CallerMemberName]
string callerName =
"")
200 var
property = GetProperty(callerName);
201 var attribute = GetRedDotAttributeOfCallerMember(callerName);
204 if (IsLanguageDependentProperty(property))
206 return GetLanguageDependentProperty<T>(attribute, property);
209 return attribute.ReadFrom<T>(project, _readWriteWrapper);
212 protected RedDotAttribute GetRedDotAttributeOfCallerMember(
string callerName)
214 const bool USE_INHERITED_ATTRIBUTES =
true;
216 var
property = GetProperty(callerName);
219 property.GetCustomAttributes(typeof (RedDotAttribute), USE_INHERITED_ATTRIBUTES).First();
222 protected virtual void SetAttributeValue<T>(T value, [CallerMemberName]
string callerName =
"")
224 var project =
this as IProjectObject;
225 var attribute = GetRedDotAttributeOfCallerMember(callerName);
227 attribute.WriteTo(project, _readWriteWrapper, value);
230 private T GetLanguageDependentProperty<T>(RedDotAttribute attribute, PropertyInfo property)
234 var contentType = typeof (T).GetGenericArguments()[0];
235 var realType = typeof (LanguageDependentValue<>).MakeGenericType(contentType);
237 realType.GetConstructor(
new[] {typeof (IPartialRedDotProjectObject), typeof (RedDotAttribute)});
240 return (T) constructor.Invoke(
new object[] {
this, attribute});
242 }
catch (Exception e)
245 string.Format(
"Internal error in construction of language dependent property {0}", property.Name), e);
249 private PropertyInfo GetProperty(
string callerName)
252 .GetProperty(callerName,
253 BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public |
254 BindingFlags.FlattenHierarchy);
257 private static bool IsLanguageDependentProperty(PropertyInfo property)
259 Func<Type, bool> isLanguageDependent =
260 x => x.IsGenericType && x.GetGenericTypeDefinition() == typeof (ILanguageDependentValue<>);
261 return isLanguageDependent(property.PropertyType) ||
262 property.PropertyType.GetInterfaces().Any(isLanguageDependent);