C# 依赖注入的创造模式

C# 依赖注入的创造模式,c#,design-patterns,dependency-injection,ninject,object-construction,C#,Design Patterns,Dependency Injection,Ninject,Object Construction,我专门将C#与Ninject一起使用,但问题不仅仅限于Ninject。我的问题是,我有几个类,它们都有不同的构造函数参数和注入的参数。我知道我可以使用kernel.Get(这里是构造函数参数)来实例化对象。我觉得这样做不对,因为我会把内核弄得到处都是。我将尽我所能在下面列出一些例子 我现在所拥有的: public interface IStore<T> { void CommitToDatabase(T item); } public abstract class Thin

我专门将C#与Ninject一起使用,但问题不仅仅限于Ninject。我的问题是,我有几个类,它们都有不同的构造函数参数和注入的参数。我知道我可以使用
kernel.Get(这里是构造函数参数)
来实例化对象。我觉得这样做不对,因为我会把内核弄得到处都是。我将尽我所能在下面列出一些例子

我现在所拥有的:

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; }
}
公共接口晶体管
{
无效佣金数据库(T项);
}
公共抽象类事物
{
私人史托尔商店;
受保护的对象(对象密钥、IStore存储)
{
钥匙=钥匙;
_商店=商店;
}
公共对象密钥{get;private set;}
公共虚拟空间更新()
{
_store.CommitToDatabase(此数据库);
}
}
公共阶层人士:事情
{
公共人物(对象键、字符串名、整数、IStore存储)
:base(键、存储)
{
名称=名称;
年龄=年龄;
}
公共字符串名称{get;private set;}
公共整数{get;私有集;}
}
公车
{
公共汽车(对象密钥、整数年、字符串制造、字符串模型、IStore存储)
:base(键、存储)
{
年=年;
制造=制造;
模型=模型;
}
公共整年{get;私有集;}
公共字符串Make{get;private set;}
公共字符串模型{get;private set;}
}
我知道在Ninject中,我可以做到以下几点:

kernel.Get<Car>(new ConstructorArgument("key", 1), new ConstructorArgument("year", 2010), new ConstructorArgument("make", "Astin Martin"), new ConstructorArgument("model", "Vanquish"));
kernel.Get(新构造器参数(“key”,1),新构造器参数(“year”,2010),新构造器参数(“make”,“Astin-Martin”),新构造器参数(“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);
    }
}
公共接口晶体管
{
无效佣金数据库(T项);
}
公共抽象类事物
{
私人史托尔商店;
保护区已初始化;
受保护对象(IStore存储)
{
Key=null;
_商店=商店;
_i初始化=错误;
}
公共对象密钥{get;private set;}
公共虚拟无效初始化(对象密钥)
{
如果(!\u已初始化){
钥匙=钥匙;
_IsInitialized=true;
}
}
公共虚拟空间更新()
{
_store.CommitToDatabase(此数据库);
}
受保护的布尔值已初始化()
{
已初始化的返回;
}
}
公共阶层人士:事情
{
公众人士(史托瑞商店)
:基地(商店)
{
Name=string.Empty;
年龄=int.MinValue;
}
公共字符串名称{get;private set;}
公共整数{get;私有集;}
公共void初始化(对象键、字符串名、整数)
{
如果(!base.isInitialized()){
名称=名称;
年龄=年龄;
}
初始化(键);
}
}
公车
{
公共汽车(史托瑞商店)
:基地(商店)
{
年份=0;
Make=“福特”;
Model=“Model T”;
}
公共整年{get;私有集;}
公共字符串Make{get;private set;}
公共字符串模型{get;private set;}
公共无效初始化(对象键、整数年、字符串生成、字符串模型)
{
如果(!base.isInitialized()){
年=年;
制造=制造;
模型=模型;
}
初始化(键);
}
}
问题:
“可能的新东西”是一种常见的做法、坏主意、好主意,但实施不佳,还是有更好的方法来实现它?

您不应该将IStore注入DTO。它们应该是普通对象。相反,将
IStore
注入当前调用
Update
并从那里调用
committedatabase
的类中

e、 g

公共类PersonService
{
专用只读存储;
公共人员服务(IStore商店)
{
this.store=商店;
}
public void CreatePerson(字符串名称,整数年龄)
{
var person=新员工(姓名、年龄);
此.store.CommitToDatabase(个人);
}
}

此外,不应使用IoC容器创建类似Person的DTO。从持久层获取它们,使用AutoMapper创建它们,或者使用
new
创建它们。但不要为它们使用IoC容器。它们不应该有任何依赖关系。

我认为首先让实体知道持久性机制是个坏主意。您可以考虑改用存储库模式。
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);
    }
}