17 using System.Globalization;
19 using erminas.SmartAPI.CMS.Project;
20 using erminas.SmartAPI.Exceptions;
22 namespace erminas.SmartAPI.CMS
24 [AttributeUsage(AttributeTargets.Property, AllowMultiple =
false, Inherited =
true)]
25 internal class RedDotAttribute :
Attribute
27 public readonly
string ElementName;
28 private IAttributeConvertBase _converterInstance;
29 private Type _converterType;
30 private string _description;
31 private bool _isReadOnly;
32 private Type _targetType;
34 public RedDotAttribute(
string elementName)
36 ElementName = elementName;
39 public Type ConverterType
41 get {
return _converterType; }
44 if (!IsConverterType(value))
47 value.Name, ElementName));
55 type.IsGenericType && type.GetGenericTypeDefinition() == typeof (IAttributeConverter<>));
56 _targetType = interfaceType.GetGenericArguments()[0];
57 _converterInstance = (IAttributeConvertBase) value.GetConstructor(
new Type[0]).Invoke(
new object[0]);
58 _converterType = value;
62 string.Format(
"Invalid converter type '{0}' for element {1}", value.Name, ElementName), e);
67 public string DependsOn {
get;
set; }
69 public string Description
71 get {
return _description ?? RedDotAttributeDescription.GetDescriptionForElement(ElementName); }
72 set { _description = value; }
75 public bool IsReadOnly
77 get {
return _converterInstance != null ? _converterInstance.IsReadOnly || _isReadOnly : _isReadOnly; }
78 set { _isReadOnly = value; }
81 public T ReadFrom<T>(
IProjectObject sourceProject, IXmlReadWriteWrapper element)
83 Type type = typeof (T);
84 return _converterInstance != null
85 ? GetCustomConversion<T>(sourceProject, element, type)
86 : GetDefaultConversion<T>(element, type);
89 public void WriteTo<T>(
IProjectObject targetProject, IXmlReadWriteWrapper element, T value)
94 string.Format(
"Cannot write to read only attribute {0}", Description));
96 if (_converterInstance != null)
98 SetWithCustomConversion(targetProject, element, value);
102 SetWithDefaultConversion(element, value);
106 private T GetCustomConversion<T>(
IProjectObject sourceProject, IXmlReadWriteWrapper element, Type type)
108 if (_targetType != type)
111 string.Format(
"Converter type does not match Convert<T> call for element {0}", ElementName));
114 return ((IAttributeConverter<T>) _converterInstance).ConvertFrom(sourceProject, element.MergedElement,
this);
117 private T GetDefaultConversion<T>(IXmlReadWriteWrapper element, Type type)
119 if (type == typeof (
string))
121 return (T) (object) element.GetAttributeValue(ElementName);
123 if (type == typeof (
bool))
125 return (T) (object) element.GetBoolAttributeValue(ElementName);
127 if (type == typeof (
int?))
129 return (T) (object) element.GetIntAttributeValue(ElementName);
132 ElementName, type.Name));
135 private static bool IsConverterType(Type value)
138 value.GetInterfaces()
140 type => type.IsGenericType && type.GetGenericTypeDefinition() == typeof (IAttributeConverter<>));
143 private void SetWithCustomConversion<T>(
IProjectObject targetProject, IXmlReadWriteWrapper element, T value)
145 if (typeof (T) != _targetType)
148 string.Format(
"Converter type {0} does not match Set<T> call for element {1} with type {2}",
149 _targetType.Name, ElementName, typeof (T).Name));
152 ((IAttributeConverter<T>) _converterInstance).WriteTo(targetProject, element,
this, value);
155 private void SetWithDefaultConversion<T>(IXmlReadWriteWrapper element, T value)
157 Type type = typeof (T);
158 if (type == typeof (
string))
160 element.SetAttributeValue(ElementName, (
string) (
object) value);
164 if (type == typeof (
bool))
166 element.SetAttributeValue(ElementName, (
bool) (
object) value ?
"1" :
"0");
169 if (type == typeof (
int?))
171 var i = ((
int?) (
object) value);
172 element.SetAttributeValue(ElementName, i != null ? i.Value.ToString(CultureInfo.InvariantCulture) : null);
176 ElementName, type.Name));