C# 接口和继承的类
晚上好,, 我第一次尝试在一个中等规模的项目中用DI实现坚实的原则。 大多数时候我理解,但现在我有麻烦了。 让我举一个糟糕的例子,但它显示了应用程序的结构。 我继承了具有不同构造函数的类(下面提供的代码)。当我需要一个实例时,我知道我需要的类。 关于这段代码,有两个问题: 1/在这种情况下,我是否必须使用接口来实现SOLID principe(或者简单地在Program.cs中声明ClassA实例,如ClassA example=new ClassA(“text”) 2/做得好吗?(什么是好的/什么是坏的,做什么/避免什么?)C# 接口和继承的类,c#,interface,inherited,C#,Interface,Inherited,晚上好,, 我第一次尝试在一个中等规模的项目中用DI实现坚实的原则。 大多数时候我理解,但现在我有麻烦了。 让我举一个糟糕的例子,但它显示了应用程序的结构。 我继承了具有不同构造函数的类(下面提供的代码)。当我需要一个实例时,我知道我需要的类。 关于这段代码,有两个问题: 1/在这种情况下,我是否必须使用接口来实现SOLID principe(或者简单地在Program.cs中声明ClassA实例,如ClassA example=new ClassA(“text”) 2/做得好吗?(什么是好的/
类程序
{
静态void Main(字符串[]参数)
{
IFactory示例=新工厂();
//使用Unity-->示例=Resolve();
GetTextClassA(“测试”);
例如,GetTextClassB(1);
Console.ReadLine();
}
}
公共接口工厂
{
ClassA GetTextClassA(字符串文本);
ClassB GetTextClassB(int-text);
}
公共类工厂:IFactory
{
公共类A GetTextClassA(字符串文本)
{
返回新的ClassA(文本);
}
公共类B GetTextClassB(int-text)
{
返回新的ClassB(文本);
}
}
公共抽象类main类
{
私有字符串_文本;
公共MainClass(){}
受保护的抽象字符串GetText();
受保护的虚拟空初始化()
{
_text=GetText();
Console.WriteLine(_text);
}
公共字符串文本显示
{
获取{return\u text;}
}
}
公共类ClassA:MainClass
{
字符串_textA;
公共类A(字符串textParam)
{
_textA=textParam;
base.Initialize();
}
受保护的重写字符串GetText()
{
return“Text is:”+\u textA;
}
}
公共类ClassB:MainClass
{
国际货币基金组织;
公共B类(国际货币)
{
_numParam=numParam;
base.Initialize();
}
受保护的重写字符串GetText()
{
return“Text is:”+_numParam.ToString();
}
}
非常感谢您的评论。您似乎没有注入任何依赖项 DI的最低要求包括两件事:
interface IServiceA
{
void Foo();
}
interface IServiceB
{
void Bar();
}
class ServiceA : IServiceA
{
public void Foo() { do something ; }
}
class ServiceB : IServiceB
{
public void Bar() { do something else; }
}
interface IProgram
{
void Execute();
}
class Program : IProgram
{
private readonly IServiceA _serviceA;
private readonly IServiceB _serviceB;
public Program(IServiceA serviceA, IServiceB serviceB)
{
_serviceA = serviceA; //Injected dependency
_serviceB = serviceB; //Injected dependency
}
public void Execute()
{
_serviceA.Foo();
_serviceB.Bar();
}
}
void Main()
{
//Composition root
var container = new UnityContainer();
container.RegisterType<IServiceA, ServiceA>();
container.RegisterType<IServiceB, ServiceB>();
container.RegisterType<IProgram, Program>();
//The one and only one entry point for Program
container.Resolve<IProgram>().Execute();
}
接口IServiceA
{
void Foo();
}
接口IServiceB
{
空心钢筋();
}
A类服务:伊瑟维西亚
{
public void Foo(){do something;}
}
B类服务:IServiceB
{
public void Bar(){执行其他操作;}
}
接口程序
{
void Execute();
}
课程名称:IProgram
{
私有只读服务器a_serviceA;
专用只读服务器b_serviceB;
公共计划(IServiceA服务A、IServiceB服务B)
{
_serviceA=serviceA;//注入依赖项
_serviceB=serviceB;//注入依赖项
}
public void Execute()
{
_serviceA.Foo();
_serviceB.Bar();
}
}
void Main()
{
//成分根
var container=new UnityContainer();
container.RegisterType();
container.RegisterType();
container.RegisterType();
//程序的唯一入口点
container.Resolve().Execute();
}
这是怎么回事
Program
是你的主修课,可以做任何事情。但它也不起任何作用。在SRP下,它将有趣的职责转移给其他类(ServiceA
和ServiceB
)。只是它不知道类是什么——只知道它需要的接口。它不知道它们来自哪里,也不知道它们是如何产生的。它们就在那里,因为它们在创建程序时被推送(注入)
Unity容器设置为注册程序所需的所有接口。它将通过构造函数参数将依赖项注入程序
(Unity会自动为您这样做)。然后,程序可以调用服务来完成工作,同样,不知道它们来自哪里
我们为什么要这样做?有几个原因
测试程序可以创建实现IServiceA
和IServiceB
的其他类(存根)。通过注入这些存根依赖项,测试可以只关注程序中的逻辑
通过将特定接口作为构造函数参数放置,可以立即清楚地看到程序所依赖的内容。如果你得到了错误的接口,程序甚至无法编译。这比等待运行时发现您需要的服务不可用要好得多(这就是为什么我们不注入Unity容器本身——在不读取所有代码的情况下,您将无法知道程序
将尝试提取哪些接口。使用或简单的静态工厂也是如此)
通过使用容器注入依赖项,还允许依赖项具有依赖项(例如,如果ServiceA
依赖于ServiceC
)。Unity容器也将注入注入类,k和注入注入类,等等
您可以在组合根目录中管理生命周期(每个请求、每个线程或每个进程),因为这就是责任所在。您不希望对象生命周期逻辑分散在整个代码库中,因为这使得在每个用户都有线程的应用程序域中运行同一个对象非常困难,而服务或Windows应用程序的生命周期规则不同
你的具体问题是什么?当您想要达到特定目标时,您正在按照模式/原则对模型进行编程。你的目标是什么?如果你不走这条路,要知道这一点,我们不应该对目前不存在的问题进行哲学思考
interface IServiceA
{
void Foo();
}
interface IServiceB
{
void Bar();
}
class ServiceA : IServiceA
{
public void Foo() { do something ; }
}
class ServiceB : IServiceB
{
public void Bar() { do something else; }
}
interface IProgram
{
void Execute();
}
class Program : IProgram
{
private readonly IServiceA _serviceA;
private readonly IServiceB _serviceB;
public Program(IServiceA serviceA, IServiceB serviceB)
{
_serviceA = serviceA; //Injected dependency
_serviceB = serviceB; //Injected dependency
}
public void Execute()
{
_serviceA.Foo();
_serviceB.Bar();
}
}
void Main()
{
//Composition root
var container = new UnityContainer();
container.RegisterType<IServiceA, ServiceA>();
container.RegisterType<IServiceB, ServiceB>();
container.RegisterType<IProgram, Program>();
//The one and only one entry point for Program
container.Resolve<IProgram>().Execute();
}