MSDN.WhiteKnight - Stack Overflow answers
Ответ на "Создание переменной определенного типа в зависимости от id"
Answer 1005370
Например, так (в предположении, что все наследники в одной сборке, и что наплевать на производительность):
using System; using System.Linq; using System.Collections.Generic; using System.Text; using System.Reflection; namespace ConsoleApp1 { abstract class Data { public static Data CreateDataInstance(int id) { var derived = typeof(Data).Assembly.GetTypes().Where(t => t.BaseType == typeof(Data)); var types = derived.Where( t => (t.GetCustomAttribute(typeof(DataIdAttribute)) as DataIdAttribute).ID == id ); if (types.Count() == 0) throw new MissingMemberException("No such type with ID "+id.ToString()); Type type = types.First(); return (Data)Activator.CreateInstance(type); } } class DataIdAttribute : Attribute { int _id; public int ID { get { return _id; } } public DataIdAttribute(int id) { _id = id; } } [DataId(1)] class DataA : Data { public override string ToString() { return "DataA"; } } [DataId(2)] class DataB : Data { public override string ToString() { return "DataB"; } } }
Если же производительность важна, но допустимы некоторые накладные расходы при первом обращении, можно предложить более громоздкое оптимизированное решение:
using System; using System.Linq; using System.Linq.Expressions; using System.Collections.Generic; using System.Text; using System.Reflection; namespace ConsoleApp1 { abstract class Data { static Dictionary<int, Delegate> delegcache = new Dictionary<int, Delegate>(); public static Data CreateDataInstance(int id) { Delegate deleg; if (delegcache.ContainsKey(id)) { deleg = delegcache[id]; } else { var derived = typeof(Data).Assembly.GetTypes().Where(t => t.BaseType == typeof(Data)); var types = derived.Where( t => (t.GetCustomAttribute(typeof(DataIdAttribute)) as DataIdAttribute).ID == id ); if (types.Count() == 0) throw new MissingMemberException("No such type with ID " + id.ToString()); Type type = types.First(); NewExpression expr = Expression.New(type); LambdaExpression lambda = Expression.Lambda(expr); deleg = lambda.Compile(); delegcache[id] = deleg; } return (Data)deleg.DynamicInvoke(); } } class DataIdAttribute : Attribute { int _id; public int ID { get { return _id; } } public DataIdAttribute(int id) { _id = id; } } [DataId(1)] class DataA : Data { public override string ToString() { return "DataA"; } } [DataId(2)] class DataB : Data { public override string ToString() { return "DataB"; } } }
Content is retrieved from StackExchange API.
Auto-generated by ruso-archive tools.