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容器。他们不应该有任何依赖。