Это сбивает с толку меня, поэтому этот вопрос, вероятно, будет сбивать с толку.
У меня есть приложение, которое использует реализации интерфейса IJob для выполнения различных задач.
public interface IJob
{
int Id { get; set; }
string Name { get; set; }
void Run();
}
Я использую Castle.Windsor.WindsorContainer для разрешения этих реализаций и использую идентификатор службы для их идентификации.
WindsorContainer container = new WindsorContainer(new XmlInterpreter());
IJob jobToExecute = container.Resolve<IJob>("nameOfJob");
Я написал небольшой универсальный метод расширения, который просто помещает значения столбцов SQL в соответствующие им свойства.
public static void MapTo<T>(this DbDataReader reader, ref T instance) where T : class
{
Type objectType = typeof(T);
foreach (PropertyInfo propertyInfo in objectType.GetProperties())
{
if (propertyInfo.CanWrite)
{
int ordinal = -1;
try
{
ordinal = reader.GetOrdinal(propertyInfo.Name);
object value = reader[ordinal] == DBNull.Value ? null : reader[ordinal];
propertyInfo.SetValue(instance, value, null);
}
catch (IndexOutOfRangeException ex)
{
continue;
}
}
}
}
Теперь, поскольку вы не можете создать экземпляр интерфейса, передача IJob этому методу не будет работать. Однако для того, чтобы получить преимущества контейнера IoC, мне нужно сделать все в моем хранилище, используя интерфейс IJob. Итак, я написал с этим, чтобы разрешить реализацию IJob и передать ее методу MapTo для заполнения необходимых свойств:
public IJob GetJobById(int id)
{
string cmdTxt = "SELECT Id, Name, Description, DateStarted, ScheduledCompletion, Completed FROM Jobs WHERE Id = @id";
using (DbCommand cmd = _dataFactory.CreateCommand(cmdTxt))
{
_dataFactory.AddParam(cmd, "id", id, DbType.Int32);
using (DbDataReader rdr = cmd.ExecuteReader())
{
if (rdr.Read())
{
IJob job = _container.Resolve<IJob>("job.implementation");
rdr.MapTo<IJob>(ref job);
return job;
}
else
{
return null;
}
}
}
}
Это правильное проектное решение? Вы видите какие-либо проблемы?