Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/295.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

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/api/5.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# 架构问题:使用依赖注入导致垃圾API_C#_Api_Architecture_Dependency Injection_Castle Windsor - Fatal编程技术网

C# 架构问题:使用依赖注入导致垃圾API

C# 架构问题:使用依赖注入导致垃圾API,c#,api,architecture,dependency-injection,castle-windsor,C#,Api,Architecture,Dependency Injection,Castle Windsor,我正在尝试创建一个类,它可以执行各种与数据库相关的低级操作,但向UI层提供一个非常简单的接口 这个类表示一组数据,所有数据都在一个特定的聚合根中,由一个ID int检索 构造函数采用四个参数: public AssetRegister(int caseNumber, ILawbaseAssetRepository lawbaseAssetRepository, IAssetChecklistKctcPartRepository assetChecklistKctcPartRepository,

我正在尝试创建一个类,它可以执行各种与数据库相关的低级操作,但向UI层提供一个非常简单的接口

这个类表示一组数据,所有数据都在一个特定的聚合根中,由一个ID int检索

构造函数采用四个参数:

public AssetRegister(int caseNumber, ILawbaseAssetRepository lawbaseAssetRepository, IAssetChecklistKctcPartRepository assetChecklistKctcPartRepository, User user)
{
  _caseNumber = caseNumber;
  _lawbaseAssetRepository = lawbaseAssetRepository;
  _assetChecklistKctcPartRepository = assetChecklistKctcPartRepository;
  _user = user;
  LoadChecklists();
}
UI层通过接口
IAssetRegister
访问此类。Castle Windsor可以提供ILawbaseAssetRepository和IAssetChecklistKctcPartRepository参数本身,但UI代码需要使用以下匿名类型提供其他两个参数:

int caseNumber = 1000;
User user = GetUserFromPage();
IAssetRegister assetRegister = Moose.Application.WindsorContainer.Resolve<IAssetRegister>(new { caseNumber, user});
var command = new RegisterAssetCommand
{
    CaseNumber = 1000,
    Operator = GetUserFromPage(),
};

var commandHandler = WindsorContainer
    .Resolve<ICommandHandler<RegisterAssetCommand>);

commandHandler.Handle(command);
public class RegisterAssetCommandHandler
    : ICommandHandler<RegisterAssetCommand>
{
    private ILawbaseAssetRepository lawbaseAssetRepository;
    private IAssetChecklistKctcPartRepository assetRepository;

    public RegisterAssetCommandHandler(
        ILawbaseAssetRepository lawbaseAssetRepository,
        IAssetChecklistKctcPartRepository assetRepository)
    {
        this.lawbaseAssetRepository = lawbaseAssetRepository;
        this.assetRepository = assetRepository;
    }

    public void Handle(RegisterAssetCommand command)
    {
        // Optionally validate the command

        // Execute the command
    }
}
int caseNumber=1000;
User=GetUserFromPage();
IAssetRegister assetRegister=Moose.Application.WindsorContainer.Resolve(新{caseNumber,user});
从API设计的角度来看,这是垃圾。UI层开发人员无法知道IAssetRegister需要一个整数和一个用户。他们需要了解类的实现才能使用它


我知道我这里一定有设计问题。有人能给我一些建议吗?

正如Morten指出的,将不可注入依赖项从构造函数调用移动到实际需要使用它的方法

如果您有无法(或很难)注入的构造函数参数,那么您也无法自动将
IAssetRegister
注入到任何需要它的类中

当然,您始终可以创建一个带有以下具体实现的
IUserProvider
接口:

public class UserProvider : IUserProvider 
{
    // interface method
    public User GetUser() 
    {
        // you obviously don't want a page dependency here but ok...
        return GetUserFromPage();
    }
}

从而创建了另一个不存在的可注入依赖项。现在,您不再需要将用户传递给可能需要它的每个方法。

尝试将消息与行为分开。创建一个保存操作数据的类,并创建一个包含该操作的业务逻辑的不同类。例如,创建以下命令:

public class RegisterAssetCommand
{
    [Required]
    public int CaseNumber { get; set; }

    [Required]
    public User Operator { get; set; }
}
现在定义一个用于处理业务命令的接口:

public interface ICommandHandler<TCommand>
{
    void Handle(TCommand command);
}
或者,您甚至可以通过在
RegisterAssetCommandHandler
中注入
IUserProvider
User
RegisterAssetCommandHandler
中退出。
IUserProvider
接口可以有一个处理程序可以调用的
GetUserForCurrentContext


我希望这是有意义的。

仅对可注入依赖项使用构造函数注入。将手动指定的值移动为方法参数,或在construction.lol@TheppDeveloper's edit之后提供一种方法来设置它们!是的,那个编辑也让我笑了。不确定你们是否真的应该这样“搞乱作者的风格个性:)不是DI导致了垃圾API。你用的是SL,这是常见的气味。不要做SL。我从来没有说DI本身会导致一个垃圾API,只是我(错误地)使用了它。对不起,我不理解这段代码。我需要更多的汤匙。如何获取IAssetRegister实例?您的
IAssetRegister
已不存在。它被分为两类:一类是
RegisterAssetCommand
,另一类是
ICommandHandler
。您在
IAssetRegister
实现中放入的代码应该放入
RegisterAssetCommandHandler
类的
Handle
方法中。哦,我想我明白了。您认为IAssetRegister只是执行一些命令。事实上,它基本上就像一个实体——它包含状态。话虽如此,我认为问题在于设计——我需要一个存储库来为我提供资产注册。然后我可以将案例编号和用户提供给存储库的加载方法。让你的实体依赖于服务通常是个坏主意,但我想你已经明白了,因为这就是你的问题所在。顺便说一句,你的博客看起来棒极了。喝了一杯浓烈的咖啡后,我会试试看的!:)这个用户提供者的想法可以为我解决几个问题。谢谢。好的,我解决了这个问题。我使用IUserProvider类型接口获取当前用户(当然是注入的),并通过方法调用而不是构造函数提供案例编号。现在,我的API不需要开发人员进行任何猜测。谢谢大家!!哦,IUserProvider的概念也为我解决了这个问题:这超出了我的期望;)