using System; public class Widget { }
using System; [AttributeUsage(AttributeTargets.Field, AllowMultiple = false)] public class WidgetNameAttribute : Attribute { public WidgetNameAttribute(string name) { this.name = name; } public string Name { get { return name; } } private string name; }
using System; using System.Reflection; public class Form { public void Initialise() { FieldInfo[] fields = GetType().GetFields( BindingFlags.FlattenHierarchy | BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); foreach (FieldInfo field in fields) { foreach (WidgetNameAttribute item in field.GetCustomAttributes( typeof(WidgetNameAttribute), false)) { Widget widget = FindWidget(item.Name); field.SetValue(this, widget); break; } } } public Widget FindWidget(string name) { return new Widget(); } }
using System; public class TestForm1 : Form { [WidgetName("Test1")] public Widget TestWidget1; [WidgetName("Test2")] public Widget TestWidget2; }
using System; namespace ConsoleApplication1 { class Program { static void Main(string[] args) { TestForm1 form1 = new TestForm1(); form1.Initialise(); } } }
using System; [AttributeUsage(AttributeTargets.Field, AllowMultiple = false)] public class DataValueAttribute : Attribute { public DataValueAttribute(string xPath) { this.xPath = xPath; } public string XPath { get { return xPath; } } private string xPath; }
using System; using System.Xml; using System.Reflection; using System.Collections.Generic; public class DataObject { static DataObject() { parsers[typeof(int)] = delegate(string value) { return int.Parse(value); }; parsers[typeof(string)] = delegate(string value) { return value; }; } public void InitialiseByXml(XmlNode node) { FieldInfo[] fields = GetType().GetFields( BindingFlags.FlattenHierarchy | BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); foreach (FieldInfo field in fields) { foreach (DataValueAttribute item in field.GetCustomAttributes( typeof(DataValueAttribute), false)) { XmlNode tergetNode = node.SelectSingleNode(item.XPath); object value = parsers[field.FieldType](tergetNode.InnerText); field.SetValue(this, value); break; } } } private delegate object ParseHandle(string value); private static Dictionary<Type, ParseHandle> parsers = new Dictionary<Type, ParseHandle>(); }
using System; public class TestDataObject1 : DataObject { [DataValue("Root/IntValue")] public int Value1; [DataValue("Root/StringValue")] public string Value2; }
using System; using System.Xml; namespace ConsoleApplication1 { class Program { static void Main(string[] args) { XmlDocument doc = new XmlDocument(); doc.LoadXml( "<Root>" + "<IntValue>42</IntValue>" + "<StringValue>Douglas Adams</StringValue>" + "</Root>"); TestDataObject1 test = new TestDataObject1(); test.InitialiseByXml(doc); } } }
using System; [AttributeUsage(AttributeTargets.Field, AllowMultiple = false)] public class CloneAttribute : Attribute { public bool Deep { get { return deep; } set { deep = value; } } private bool deep; }
using System; using System.Reflection; public class CloneableObject : ICloneable { public object Clone() { object clone = Activator.CreateInstance(GetType()); FieldInfo[] fields = GetType().GetFields( BindingFlags.FlattenHierarchy | BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); foreach (FieldInfo field in fields) { foreach (CloneAttribute item in field.GetCustomAttributes( typeof(CloneAttribute), false)) { object value = field.GetValue(this); if (item.Deep) { if (field.FieldType.IsArray) { Array oldArray = (Array)value; Array newArray = (Array)oldArray.Clone(); for (int index = 0; index < oldArray.Length; index++) newArray.SetValue(((ICloneable)oldArray.GetValue(index)). Clone(), index); value = newArray; } else { value = ((ICloneable)value).Clone(); } } field.SetValue(clone, value); break; } } return clone; } }
using System; public class TestCloneableObject1 : CloneableObject { [Clone] public CloneableObject Value1; [Clone] public CloneableObject[] ValueArray2; [Clone(Deep = true)] public CloneableObject Value3; [Clone(Deep = true)] public CloneableObject[] ValueArray4; }
using System; namespace ConsoleApplication1 { class Program { static void Main(string[] args) { TestCloneableObject1 test = new TestCloneableObject1(); test.Value1 = new CloneableObject(); test.ValueArray2 = new CloneableObject[] { new CloneableObject() }; test.Value3 = new CloneableObject(); test.ValueArray4 = new CloneableObject[] { new CloneableObject() }; TestCloneableObject1 test2 = (TestCloneableObject1)test.Clone(); } } }
using System; public class TestObject1 { [Clone, DataValue("Root/IntValue")] public int Value1; [DataValue("Root/StringValue")] public string Value2; [Clone, WidgetName("Test1")] public Widget Widget3; }
using System; using System.Reflection; [AttributeUsage(AttributeTargets.Field, AllowMultiple = true)] public abstract class FieldSetterAttribute : Attribute { public abstract void Generate(Initialiser initialiser, FieldInfo info); }
using System; using System.Collections.Generic; public delegate void InitialiseHandle(object target, object data); public class Initialiser { public void Add(InitialiseHandle handle) { handlers.Add(handle); } public void Initialise(object target, object data) { foreach (InitialiseHandle handler in handlers) handler(target, data); } private List<InitialiseHandle> handlers = new List<InitialiseHandle>(); }
using System; using System.Collections.Generic; public class Container { public Initialiser GetInitialiser(Type type) { Initialiser result; if (!initialisers.TryGetValue(type, out result)) { result = new Initialiser(); initialisers.Add(type, result); } return result; } private Dictionary<Type, Initialiser> initialisers = new Dictionary<Type, Initialiser>(); }
using System; using System.Collections.Generic; using System.Reflection; public static class TypeManager { public static Container GetContainer(Type type) { Container result; if (!containers.TryGetValue(type, out result)) { result = new Container(); containers.Add(type, result); InitialiseContainer(type, result); } return result; } private static void InitialiseContainer(Type type, Container container) { FieldInfo[] fields = type.GetFields( BindingFlags.FlattenHierarchy | BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); foreach (FieldInfo field in fields) { foreach (FieldSetterAttribute item in field.GetCustomAttributes( typeof(FieldSetterAttribute), false)) { Initialiser initialiser = container.GetInitialiser(item.GetType()); item.Generate(initialiser, field); } } } private static Dictionary<Type, Container> containers = new Dictionary<Type, Container>(); }
using System; public class TestObject2 : Form, ICloneable { [Clone, DataValue("Root/IntValue")] public int Value1; [DataValue("Root/StringValue")] public string Value2; [Clone(Deep = true), WidgetName("Test1")] public Widget Widget3; public object Clone() { object clone = Activator.CreateInstance(GetType()); TypeManager.GetContainer(GetType()). GetInitialiser(typeof(CloneAttribute)).Initialise(clone, this); return clone; } }
using System; public class Widget : ICloneable { public object Clone() { return new Widget(); } }
using System; public class Form { public void Initialise() { TypeManager.GetContainer(GetType()). GetInitialiser(typeof(WidgetNameAttribute)).Initialise(this, null); } public Widget FindWidget(string name) { return new Widget(); } }
using System; using System.Reflection; [AttributeUsage(AttributeTargets.Field, AllowMultiple = false)] public class WidgetNameAttribute : FieldSetterAttribute { public WidgetNameAttribute(string name) { this.name = name; } public override void Generate(Initialiser initialiser, FieldInfo info) { initialiser.Add( delegate(object target, object data) { Form targetForm = (Form)target; Widget widget = targetForm.FindWidget(name); info.SetValue(targetForm, widget); } ); } private string name; }
using System; using System.Reflection; using System.Xml; using System.Collections.Generic; [AttributeUsage(AttributeTargets.Field, AllowMultiple = false)] public class DataValueAttribute : FieldSetterAttribute { static DataValueAttribute() { parsers[typeof(int)] = delegate(string value) { return int.Parse(value); }; parsers[typeof(string)] = delegate(string value) { return value; }; } public DataValueAttribute(string xPath) { this.xPath = xPath; } public override void Generate(Initialiser initialiser, FieldInfo info) { ParseHandle parser = parsers[info.FieldType]; initialiser.Add( delegate(object target, object data) { XmlNode node = ((XmlNode)data).SelectSingleNode(xPath); object value = parser(node.InnerText); info.SetValue(target, value); } ); } private string xPath; private delegate object ParseHandle(string value); private static Dictionary<Type, ParseHandle> parsers = new Dictionary<Type, ParseHandle>(); }
using System; using System.Reflection; [AttributeUsage(AttributeTargets.Field, AllowMultiple = false)] public class CloneAttribute : FieldSetterAttribute { public override void Generate(Initialiser initialiser, FieldInfo info) { if (deep) { if (info.FieldType.IsArray) { initialiser.Add( delegate(object target, object data) { object value = info.GetValue(data); Array oldArray = (Array)value; Array newArray = (Array)oldArray.Clone(); for (int index = 0; index < oldArray.Length; index++) newArray.SetValue(((ICloneable)oldArray.GetValue(index)). Clone(), index); value = newArray; info.SetValue(target, value); } ); } else { initialiser.Add( delegate(object target, object data) { object value = info.GetValue(data); value = ((ICloneable)value).Clone(); info.SetValue(target, value); } ); } } else { initialiser.Add( delegate(object target, object data) { object value = info.GetValue(data); info.SetValue(target, value); } ); } } public bool Deep { get { return deep; } set { deep = value; } } private bool deep; }
Source: https://habr.com/ru/post/168477/
All Articles