Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/275.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 简单依赖解析程序_C#_Design Patterns_Dependency Injection - Fatal编程技术网

C# 简单依赖解析程序

C# 简单依赖解析程序,c#,design-patterns,dependency-injection,C#,Design Patterns,Dependency Injection,如何在不使用任何内置或库(如Autofac、Ninject等)的情况下创建简单的依赖项解析器 这是我的面试问题 我写了这个简单的代码,他们说它看起来不好。这就像是一个硬编码的想法 public interface IRepository { } interface IDataProvider { List<string> GetData(); } public class SQLDataProvider : IDataProvider { private readon

如何在不使用任何内置或库(如Autofac、Ninject等)的情况下创建简单的依赖项解析器

这是我的面试问题

我写了这个简单的代码,他们说它看起来不好。这就像是一个硬编码的想法

public interface IRepository { }
interface IDataProvider
{
    List<string> GetData();
}
public class SQLDataProvider : IDataProvider
{
    private readonly IRepository _repository { get; set; }
    public SQLDataProvider(IRepository repository)
    {
        _repository = repository;
    }
    public List<string> GetData()
    {
        return new List<string> { "" };
    }
}
public class MockDataProvider : IDataProvider
{
    public List<string> GetData()
    {
        return new List<string> { "" };
    }
}
class Program
{
 static void Main(string[] args)
 {
    string targetClass = "SQLDataProvider";
    //Here i need to supply IRepository instance too 
   IDataProvider dataProvider = 
   (IDataProvider)Activator.CreateInstance(typeof(IDataProvider), targetClass);

  }
}
公共接口IRepository{}
接口IDataProvider
{
List GetData();
}
公共类SQLDataProvider:IDataProvider
{
私有只读存储库{get;set;}
公共SQLDataProvider(IRepository存储库)
{
_存储库=存储库;
}
公共列表GetData()
{
返回新列表{”“};
}
}
公共类MockDataProvider:IDataProvider
{
公共列表GetData()
{
返回新列表{”“};
}
}
班级计划
{
静态void Main(字符串[]参数)
{
字符串targetClass=“SQLDataProvider”;
//在这里,我还需要提供IRepository实例
IDataProvider数据提供程序=
(IDataProvider)Activator.CreateInstance(typeof(IDataProvider),targetClass);
}
}

还有什么更好的代码可以为构造函数参数提供其他对象实例呢?

它已经有几年的历史了,但Ayende曾经写过一篇关于这一点的博文:

但这只是最简单的可能实现。
Ayende自己在他的报告中指出,现有的IoC容器可以做的事情远远不止返回类实例,这就是它变得复杂的原因。
正如“相信我,我是一名医生”在他的评论中所说的那样:实现一个完整的IoC容器绝非小事。

是复杂的库。建造它们需要数年时间,维护它们需要数十年。但是为了演示它们的工作原理,您可以用几行代码编写一个简单的实现

DI容器的核心通常会包装一个字典,其键为
System.Type
,值是允许您创建该类型的新实例的某个对象。当您编写一个过于简单的实现时,
System.Func
就可以了。下面的示例包含几个
寄存器
方法,包括通用和非通用的
GetInstance
方法,并允许自动连接:

公共类容器
{
Dictionary regs=新字典();
公共无效寄存器(),其中TImpl:TService=>
this.regs.Add(typeof(TService),()=>this.GetInstance(typeof(TImpl));
公共无效寄存器(Func instanceCreator)=>
this.regs.Add(typeof(TService),()=>instanceCreator());
public void RegisterInstance(TService实例)=>
this.regs.Add(typeof(TService),()=>实例);
公共无效注册表单例(Func instanceCreator){
var lazy=新的lazy(instanceCreator);
这个.Register(()=>lazy.Value);
}
公共对象GetInstance(类型){
Func创建者;
if(this.regs.TryGetValue(type,out creator))返回creator();
否则,如果(!type.isastract)返回此.CreateInstance(type);
否则会抛出新的InvalidOperationException(“没有注册”+类型);
}
私有对象CreateInstance(类型implementationType){
var-ctor=implementationType.GetConstructors().Single();
var parameterTypes=ctor.GetParameters().Select(p=>p.ParameterType);
var相关性=
parameterTypes.Select(t=>this.GetInstance(t)).ToArray();
返回Activator.CreateInstance(implementationType,dependencies);
}
}
您可以按如下方式使用它:

var container=newcontainer();
container.RegisterInstance(新文件记录器(“c:\\logs\\log.txt”);
//SqlUserRepository依赖于ILogger
container.Register();
//HomeController依赖于IUserRepository
//具体的例子不需要解决
GetInstance(typeof(HomeController));
警告

请注意,您永远不应该实际使用这种幼稚和简单的实现。它缺少DI库提供的许多重要特性,但与使用(即手动连接对象图)相比没有优势。您失去了编译时支持,没有得到任何回报。

当你的应用程序很小的时候,你应该从纯DI开始,一旦你的应用程序和你的DI配置增长到维护你变得笨拙的程度,你可以考虑切换到一个已建立的DI库。 与已建立的库相比,此幼稚实现缺少以下一些功能:

  • 自动注册;用一行注册一组类型
  • 拦截;对一系列类型应用装饰器或拦截器的能力
  • 仿制药;将开放泛型抽象映射到开放泛型实现
  • 整合;将库与通用应用程序平台(如ASP.NET MVC、Web API、.NET Core等)一起使用
  • 生活方式管理;使用自定义生活方式注册类型的能力
  • 错误处理;检测错误配置,如循环依赖。简单化的实现引发堆栈溢出异常
  • 核实;用于验证配置正确性(以补偿编译时支持的损失)和诊断常见配置错误的功能或工具
  • 表现;使用这种过于简单的实现,构建大型对象图的速度会很慢

这些特性和功能允许您在使用DI容器时保持DI配置的可维护性。

大多数IoC容器都是开源的,例如和,因此您可以从中获得灵感。警告之词-实现并不是微不足道的。顺便说一句,这是一个极其迟钝的面试问题。这个问题似乎离题了,因为它基本上要求进行代码审查。它应该放在“代码审查”上。相关:我投票结束这个问题,因为它要求对codeHere container.GetI进行评论