C# 构造函数注入和构造函数重载

发布于 2024-11-13 10:10:18 字数 580 浏览 2 评论 0原文

我是第一次使用构造函数注入,并希望以防御性方式编写代码。

因此,如果我有一个带有构造函数和保存方法的类,如下所示:

public SomeConstructor(string name, Object someObject)
{
  _name= name;
  _someObject= someObject;
}

public void Save()
{
  // Does a database save
}

但是然后需要在该类中创建另一个不需要 _someObject 的相关方法,因此我创建一个重载的链式构造函数:

public SomeConstructor(string name) : this(name, null)
{
}

如何成功地阻止某人实例化具有带有 1 个参数的第二个构造函数并使用将 someObject 设为 null 的 Save() 的类?

我没有使用注射工具。

上面是一个简单的示例,在其中,你是对的,我可以抛出一个 null 异常,就像未设置属性时一样。

我想避免的是在每个方法开始时进行一系列验证检查。

I'm using constructor injection for the first time and wish to write my code defensively.

Therefore if I have a class with a constructor and a save method as below:

public SomeConstructor(string name, Object someObject)
{
  _name= name;
  _someObject= someObject;
}

public void Save()
{
  // Does a database save
}

But then need to create another related method in this Class that doesn't need the _someObject so I create an overloaded chained constructor as:

public SomeConstructor(string name) : this(name, null)
{
}

How can I successfully stop someone instantiating the class with this second constructor with 1 parameter and using the Save() which has someObject as null?

I'm not using an injection tool.

Above is a simple example and in it, you are correct I could just throw an exception for a null just as I would if a property was not set.

What I wanted to avoid was a series of validation checks at the start of each method.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

南七夏 2024-11-20 10:10:18

将您遇到的摩擦用作警告系统。这实际上是在告诉您,您可能正在走向低凝聚力并违反单一责任原则

如果是这种情况,请将该类重构为两个单独的类。

Use the friction you are experiencing as a warning system. It's really telling you that you're likely moving towards low cohesion and violation of the Single Responsibility Principle.

If this is the case, refactor the class into two separate classes.

樱花坊 2024-11-20 10:10:18

您可以使用 InvalidOperationException 等运行时异常来防止这种情况。

如果某些人使用两个参数构造函数实例化该类并尝试调用 Save,只需检查“someObject”是否为 null,如果是的话:

抛出 new InvalidOperationException(“无法在当前对象状态下调用此方法” );

另一方面,如果您的库将使用第二个构造函数,并且不允许第三方库开发人员使用它,则该构造函数应该具有内部修饰符。

You may prevent that situation with a run-time exception like InvalidOperationException.

If some instantiated the class with the two-parameters-constructor and tries to call Save, just check if "someObject" is null, and if it's so:

throw new InvalidOperationException("This method cannot be invoked in current object state");

In the other hand, if this second constructor would be used by your library and third-party library developers wouldn't be allowed to use it, this constructor should have the internal modifier.

天煞孤星 2024-11-20 10:10:18

IoC 它只是一种动态解决依赖关系的方法,但并不能解决任何 OO 问题。
我会专注于良好的 OO 设计,而不是试图找到一种方法来欺骗框架,迫使使用承包商而不是另一个承包商。问题是,如果您不使用 IoC 框架,您将如何做到这一点?
可能检查 SomeObject 是否为空?

The IoC it is just a way to dinamically resolve the dependency but doens't solve any OO problem.
I would focus on a good OO design instead of try to find a way to cheat the framework forcing to use a contractor instead of another.The question is how would you do that if you were not using an IoC framework?
probabily checking if SomeObject is null?

述情 2024-11-20 10:10:18
public void Save()
{  
    if (_someObject == null)
        throw new InvalidOperationException();
}

我想这是显而易见的。但是,您确实无法创建一个以不同方式构造类型的合约,除非您还更改 SomeConstructor 类型以像 装饰器模式。装饰器模式的作用是让您在运行时而不是编译时构建继承层次结构。

然后,您可以根据内部允许的操作创建不同的对象。这是一些可以通过 Save 方法的前提条件轻松处理的工作。但也许这就是您所需要的。如果您这样做了,您可以在 SomeConstructor 的构造函数中规定您的契约。

下面是一个示例:

interface ISomeConstructor
{
    void Save();
}

class SomeConstructor
{
    ISomeConstructor impl;

    public SomeConstructor(string name, object someObject)
    {
        impl = new StringAndObject(name, someObject);
    }

    public SomeConstructor(string name)
    {
        impl = new JustString(name);
    }

    public void Save()
    {
        impl.Save();
    }
}

StringAndObjectJustString 类型实现了 ISomeConstructor 并且它们可以根据需要处理 Save 方法。

这是装饰器模式的一个细微变化,通常您希望 ISomeConstructor 也作为参数传递给构造函数。

public void Save()
{  
    if (_someObject == null)
        throw new InvalidOperationException();
}

I guess that this is obvious. But you really can't create a contract in which the type is constructed differently unless you also change your SomeConstructor type to work like a decorator pattern. What the decorator pattern does is that it let's you build the inheritance hierarchy at run-time not compile-time.

You can then create different objects depending on what operations are allowed internally. This is some work for something which can easily be handled with a pre-condition for the Save method. But maybe this is what you need. And if you did it you could stipulate your contract in the constructor of SomeConstructor.

Here's an example:

interface ISomeConstructor
{
    void Save();
}

class SomeConstructor
{
    ISomeConstructor impl;

    public SomeConstructor(string name, object someObject)
    {
        impl = new StringAndObject(name, someObject);
    }

    public SomeConstructor(string name)
    {
        impl = new JustString(name);
    }

    public void Save()
    {
        impl.Save();
    }
}

The types StringAndObject and JustString implements ISomeConstructor and they can handle the Save method as they see fit.

This is a slight variation of the decorator pattern as normally you'd expect ISomeConstructor to be passed as an argument to the constructor as well.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文