Я пишу свободный интерфейс, который используется следующим образом:
xmlBuilder
.CreateFrom()
.DataSet(someDataSet) //yes I said Dataset, I'm working with a legacy code
.IgnoreSchema()
.Build
Метод IgnoreSchema()
может иметь вместо него WithSchema()
или WithDiffGrame()
.Они сопоставляются с методом WriteXml()
DataSet, который принимает следующее перечисление:
- XmlWriteMode.WriteSchema
- XmlWriteMode.DiffGram
- XmlWriteMode.IgnoreSchema
Мой свободный API вызывает то, что равнозначно фабричному объекту, который будет создавать XML из набора данных.У меня есть абстрактный тип, который обладает основной функциональностью, а затем 3 производных типа, которые отражают различные состояния, реализующие метод WriteXmlFromDataSet
(я считаю, что этот подход называется шаблоном состояний).Вот абстрактный базовый класс:
public abstract class DataSetXmlBaseFactory : IDataSetXmlFactory
{
...
protected abstract void WriteXmlFromDataSet(XmlTextWriter xmlTextWriter);
public XmlDocument CreateXmlDocument()
{
XmlDocument document = new XmlDocument();
using (StringWriter stringWriter = new StringWriter())
{
using (XmlTextWriter xmlTextWriter = new XmlTextWriter(stringWriter))
{
WriteXmlFromDataSet(xmlTextWriter);
string content = stringWriter.ToString();
document.LoadXml(content);
return document;
}
}
}
}
Это работает, конечно, но когда я собираюсь использовать этот код с Dependency Injection, у меня возникают проблемы с методами в моем беглом интерфейсе, упомянутом в начале.Ниже приведена реализация этих методов:
public IXmlBuild<T> WithSchema()
{
var xmlFactory = new DataSetXmlWithSchemaFactory(this.DataSet);
return GetIXmlBuild(xmlFactory);
}
public IXmlBuild<T> IgnoreSchema()
{
var xmlFactory = new DataSetXmlIgnoreSchemaFactory(this.DataSet);
return GetIXmlBuild(xmlFactory);
}
public IXmlBuild<T> WithSchemaAndDiffGram()
{
var xmlFactory = new DataSetXmlWithDiffGramFactory(this.DataSet);
return GetIXmlBuild(xmlFactory);
}
private static IXmlBuild<T> GetIXmlBuild(IDataSetXmlFactory xmlFactory)
{
string content = xmlFactory.CreateXmlDocument().InnerXml;
return new clsXmlDataSetBuild<T>(content);
}
Прямо сейчас я не использую Dependency Injection (DI), так как я обновляю зависимые IDataSetXMLFactory
объекты.Если бы я изменил код для использования DI, как бы класс узнал, какую реализацию IDataSetXmlFactory использовать?Если я правильно понимаю DI, это решение нужно будет принимать выше стека вызовов (в частности, в корне композиции), но там код не будет знать, какая именно реализация необходима.Если бы я использовал контейнер DI для разрешения (определения местоположения) необходимой реализации в описанных выше методах, то я бы использовал контейнер DI в качестве локатора службы, который считается анти-шаблоном.
На этом этапе было бы намного проще просто передать перечисление методу xmlFactory.CreateXmlDocument()
в экземпляре IXmlDataSetFactory.Это, конечно, намного проще и требует меньше кода, но я уверен, что с этой проблемой ранее сталкивались шаблоны состояний и DI.Как с этим справиться?Я новичок в DI и начал читать Внедрение зависимостей в .NET , но пока что ничего не прочитал по этой конкретной проблеме.
Надеюсь, я просто пропускаю небольшой кусочекзагадка.
Обновление (на основе ответа Марка Симанна)
Что будет семантической моделью для интерфейса нижепохожи? Примеры приветствуются.
public interface IXmlBuilder<T>
{
IXmlSourceContent<T> CreateFrom();
}
public interface IXmlSourceContent<T>
{
IXmlOptions<T> Object(T item);
IXmlOptions<T> Objects(IEnumerable<T> items);
IXmlDataSetOptions<T> DataSet(T ds);
IXmlBuild<T> InferredSchema();
}
public interface IXmlOptions<T> : IXmlBuild<T>
{
IXmlBuild<T> WithInferredSchema();
}
public interface IXmlDataSetOptions<T> : IXmlDataSetSchema<T>
{
IXmlDataSetSchema<T> IncludeTables(DataTableCollection tables);
IXmlDataSetSchema<T> IncludeTable(DataTable table);
}
public interface IXmlBuild<T>
{
XmlDocument Build();
}
public interface IXmlDataSetSchema<T>
{
IXmlBuild<T> WithSchemaAndDiffGram();
IXmlBuild<T> WithSchema();
IXmlBuild<T> IgnoreSchema();
}
В дополнение к упомянутой выше IDataSetXMLFactory у меня также есть следующие методы расширения:
static class XmlDocumentExtensions
{
[Extension()]
public static void InsertSchema(XmlDocument document, XmlSchema schema)
{
...
}
}
static class XmlSchemaExtensions
{
[Extension()]
public static string ToXmlText(XmlSchema schema)
{
...
}
}
и эти классы:
public class XmlFactory<T>
{
...
public XmlFactory(IEnumerable<T> objects)
{
this.Objects = objects;
}
public XmlDocument CreateXml()
{
// serializes objects to XML
}
}
public class XmlSchemaFactory<T> : IXmlSchemaFactory<T>
{
public XmlSchema CreateXmlSchema()
{
// Uses reflection to build schema from type
}
}