我会回答你的第二个问题。我想你也会对Dependency Injection
.
我不是 DI 方面的专家,但我会尽量解释清楚。
首先,来自维基百科:
依赖注入是一种软件设计模式,它允许删除硬编码的依赖关系,并可以在运行时或编译时更改它们。
依赖注入模式的主要目的是允许在运行时或通过配置文件而不是在编译时选择给定依赖接口的多个实现。
周围有许多库可以帮助您实现这种设计模式:AutoFac、SimpleInjector、Ninject、Spring .NET 等等。
理论上,这就是您的代码的样子(AutoFac 示例)
var containerBuilder = new ContainerBuilder();
//This is your container builder. It will be used to register interfaces
// with concrete implementations
然后,为接口类型注册具体实现:
containerBuilder.RegisterType<MockDatabase>().As<IDatabase>().InstancePerDependency();
containerBuilder.RegisterType<Person>().As<IPerson>().InstancePerDependency();
在这种情况下,InstancePerDependency
意味着每当您尝试解析时IPerson
,您都会获得一个新实例。例如SingleInstance
,可能是这样,所以每当您尝试解析时IPerson
,您都会得到相同的共享实例。
然后你构建你的容器,并使用它:
var container = containerBuilder.Build();
IPerson myPerson = container.Resolve<IPerson>(); //This will retrieve the object based on whatever implementation you registered for IPerson
myPerson.Id = 1;
myPerson.Save(); //Save your changes
我在这个例子中使用的模型:
interface IEntity
{
int Id { get; set; }
string TableName { get; }
//etc
}
interface IPerson: IEntity
{
void Save();
}
interface IDatabase
{
void Save(IEntity entity);
}
class SQLDatabase : IDatabase
{
public void Save(IEntity entity)
{
//Your sql execution (very simplified)
//yada yada INSERT INTO entity.TableName VALUES (entity.Id)
//If you use EntityFramework it will be even easier
}
}
class MockDatabase : IDatabase
{
public void Save(IEntity entity)
{
return;
}
}
class Person : IPerson
{
IDatabase _database;
public Person(IDatabase database)
{
this._database = database;
}
public void Save()
{
_database.Save(this);
}
public int Id
{
get;
set;
}
public string TableName
{
get { return "Person"; }
}
}
不用担心,AutoFac 会自动解析任何Person
Dependencies,例如IDatabase
.
这样,如果您想切换数据库,您可以简单地执行以下操作:
containerBuilder.RegisterType<SqlDatabase>().As<IDatabase>().InstancePerDependency();
我写了一个过度简化(不适合使用)的代码,它只是作为一个启动,谷歌“依赖注入”以获取更多信息。我希望这有帮助。祝你好运。