Как найти реализацию интерфейса C# в текущей сборке с определенным именем?
-
09-06-2019 - |
Вопрос
У меня есть интерфейс под названием IStep
который может выполнять некоторые вычисления (см. "Казнь в царстве существительных").Во время выполнения я хочу выбрать подходящую реализацию по имени класса.
// use like this: IStep step = GetStep(sName);
Решение
Ваш вопрос очень запутанный...
Если вы хотите найти типы, реализующие IStep, сделайте следующее:
foreach (Type t in Assembly.GetCallingAssembly().GetTypes())
{
if (!typeof(IStep).IsAssignableFrom(t)) continue;
Console.WriteLine(t.FullName + " implements " + typeof(IStep).FullName);
}
Если вы уже знаете имя нужного типа, просто сделайте это
IStep step = (IStep)Activator.CreateInstance(Type.GetType("MyNamespace.MyType"));
Другие советы
Если реализация имеет конструктор без параметров, это можно сделать с помощью класса System.Activator.Помимо имени класса вам нужно будет указать имя сборки:
IStep step = System.Activator.CreateInstance(sAssemblyName, sClassName).Unwrap() as IStep;
http://msdn.microsoft.com/en-us/library/system.activator.createinstance.aspx
Основываясь на том, что указывали другие, вот что я в итоге написал:
/// /// Some magic happens here: Find the correct action to take, by reflecting on types /// subclassed from IStep with that name. /// private IStep GetStep(string sName) { Assembly assembly = Assembly.GetAssembly(typeof (IStep)); try { return (IStep) (from t in assembly.GetTypes() where t.Name == sName && t.GetInterface("IStep") != null select t ).First().GetConstructor(new Type[] {} ).Invoke(new object[] {}); } catch (InvalidOperationException e) { throw new ArgumentException("Action not supported: " + sName, e); } }
Что ж, кажется, что Assembly.CreateInstance - это правильный путь - единственная проблема в том, что для этого требуется полное имя типа, т.е.включая пространство имен.