Шаблоны для внедрения зависимостей - PullRequest
4 голосов
/ 16 ноября 2011

Я специально использую C # с Ninject, но проблема выходит за рамки только Ninject.Моя проблема в том, что у меня есть несколько классов с разными аргументами конструктора плюс введенные.Я знаю, что могу использовать kernel.Get<MyObject>(constructor args here) для создания экземпляров объектов.Это не правильно для меня, так как у меня есть ядро ​​повсюду.Я приложу все усилия, чтобы перечислить примеры ниже.

Что у меня сейчас есть:

public interface IStore<T>
{
    void CommitToDatabase(T item);
}

public abstract class Thing
{
    private IStore<Thing> _store;

    protected Thing(object key, IStore<Thing> store)
    {
        Key = key;
        _store = store;
    }

    public object Key { get; private set; }

    public virtual void Update()
    {
        _store.CommitToDatabase(this);
    }
}

public class Person :Thing
{
    public Person(object key, string name, int age, IStore<Thing> store)
        : base(key, store)
    {
        Name = name;
        Age = age;
    }

    public string Name { get; private set; }
    public int Age { get; private set; }
}

public class Car :Thing
{
    public Car(object key, int year, string make, string model, IStore<Thing> store)
        : base(key, store)
    {
        Year = year;
        Make = make;
        Model = model;
    }

    public int Year { get; private set; }    
    public string Make { get; private set; }
    public string Model { get; private set; }
}

Я знаю в Ninject, что могу сделать следующее:

kernel.Get<Car>(new ConstructorArgument("key", 1), new ConstructorArgument("year", 2010), new ConstructorArgument("make", "Astin Martin"), new ConstructorArgument("model", "Vanquish"));

но мне это не кажется правильным.Я думал о том, чтобы изменить его на метод Initialize, но я не уверен, что это лучший метод или есть лучший способ.

Возможные новые вещи:

public interface IStore<T>
{
    void CommitToDatabase(T item);
}

public abstract class Thing
{
    private IStore<Thing> _store;

    protected bool _isInitialised;

    protected Thing(IStore<Thing> store)
    {
        Key = null;
        _store = store;
        _isInitialised = false;
    }

    public object Key { get; private set; }

    public virtual void Initialize(object key)
    {
        if (!_isInitialised) {
            Key = key;
            _isInitialised = true;
        }
    }

    public virtual void Update()
    {
        _store.CommitToDatabase(this);
    }

    protected bool IsInitialised()
    {
        return _isInitialised;
    }
}

public class Person :Thing
{
    public Person(IStore<Thing> store)
        : base(store)
    {
        Name = string.Empty;
        Age = int.MinValue;
    }

    public string Name { get; private set; }
    public int Age { get; private set; }

    public void Initialize(object key, string name, int age)
    {
        if (!base.IsInitialised()) {
            Name = name;
            Age = age;
        }

        base.Initialize(key);
    }
}

public class Car :Thing
{
    public Car(IStore<Thing> store)
        : base(store)
    {
        Year = 0;
        Make = "Ford";
        Model = "Model T";
    }

    public int Year { get; private set; }
    public string Make { get; private set; }
    public string Model { get; private set; }

    public void Initialize(object key, int year, string make, string model)
    {
        if (!base.IsInitialised()) {
            Year = year;
            Make = make;
            Model = model;
        }

        base.Initialize(key);
    }
}

Вопрос: Является ли «Возможные новые вещи» обычной практикой, плохой идеей, хорошей идеей с плохой реализацией или есть лучший способ сделать это вообще?

1 Ответ

6 голосов
/ 16 ноября 2011

Вы не должны вводить IStore в свои DTO. Они должны быть простыми предметами. Вместо этого введите IStore<IThing> в классы, которые в данный момент вызывают Update и оттуда CommitToDatabase.

, например

public class PersonService
{
    private readonly IStore<Person> store;
    public PersonService(IStore<Person> store)
    {
       this.store = store;
    }

    public void CreatePerson(string name, int age)
    {
       var person = new Person(name, age);
       this.store.CommitToDatabase(person);
    }
}

Также DTO, такие как Person, не должны создаваться с использованием контейнера IoC. Получите их из своего слоя персистентности, создайте их с помощью AutoMapper или создайте их с помощью new. Но не используйте контейнер IoC для них. У них не должно быть никаких зависимостей.

...