4

我特別使用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); 
    } 
} 

問: 是「可能的新的東西」的普遍做法,好主意,好主意執行不力,或者是有沒有更好的方式來完全做到這一點?

+0

我認爲讓您的實體首先意識到持久性機制是個壞主意。您可以考慮使用Repository模式。 – tvanfosson

回答

6

您不應該將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); 
    } 
} 

另外,像Person這樣的DTO不應該使用IoC容器來創建。從持久層獲取它們,使用AutoMapper創建它們或使用new創建它們。但不要爲它們使用IoC容器。他們不應該有任何依賴。