Я работаю над унаследованным кодом, который выглядит очень похоже на это:
public class BaseParser
{
public BaseParser(Stream stream)
{
// Do something with stream
}
}
public class JsonParser : BaseParser
{
public JsonParser(Stream stream)
: base(stream)
{
// Do something
}
}
public class XmlParser : BaseParser
{
public XmlParser(Stream stream, string someOtherParam)
: base(stream)
{
// Do something
}
}
У нас есть приложение, которое анализирует входящие файлы с помощью определенного анализатора.Чтобы определить, какой тип нам нужно создать, в фабричном методе есть большой блок IF / ELSE:
public static BaseParser Create(string type)
{
if (type == "xml")
return new XmlParser(new FileStream("path", FileMode.Open), "test");
if (type == "json")
return new JsonParser(new FileStream("path", FileMode.Open));
// more...
return null;
}
Так как в одной сборке находится большое количество анализаторов (давайте назовем его Demo.dll
) Я бы хотел разделить каждый из этих парсеров на свои собственные сборки.Классы «core», такие как BaseParser
, останутся в Demo.dll
, а остальные парсеры и любые зависимости будут жить в Demo.Json.dll
, Demo.Xml.dll
и т. Д. *
Ядро"библиотека загрузит эти сборки во время выполнения.
string[] paths = Directory.GetFiles(Environment.CurrentDirectory, "Demo.*.dll");
foreach (string path in paths)
Assembly.LoadFrom(path);
List<BaseParser> parsers = AppDomain.CurrentDomain
.GetAssemblies()
.SelectMany(x => x.GetTypes())
.Where(x => x.IsSubclassOf(typeof(BaseParser)))
.Select(x => (BaseParser) Activator.CreateInstance(x))
.ToList();
Проблема начинается здесь.Приведенный выше код не будет работать, так как каждый из старых анализаторов не имеет конструктора без параметров.Кроме того, я не могу придумать хороший способ заменить блок IF / ELSE и позволить каждому анализатору определить, какой файл он может обрабатывать.Я думал о возможном добавлении виртуального метода в базовый анализатор:
public virtual bool ShouldHandle(string type)
{
return false;
}
... и каждый производный синтаксический анализатор будет переопределять этот виртуальный метод.Однако есть две проблемы:
Нет конструктора без параметров, и конструктор каждого класса может иметь различное количество параметров.Это не то, что я могу изменить, так как эти унаследованные классы используются везде.
Мне нужно создать экземпляр класса, прежде чем я смогу вызвать метод ShouldHandle
.Это создает проблему для классов, которые читают из потока в конструкторе.
Есть ли альтернативный путь, которым я могу воспользоваться, чтобы разбить эти парсеры на их собственные сборки?
РЕДАКТИРОВАТЬ:
Это приложение .NET 3.5.К сожалению, нет MEF.