C# 如何存储派生类中用于初始化其基类的工厂?

C# 如何存储派生类中用于初始化其基类的工厂?,c#,.net,constructor,initialization,factory,C#,.net,Constructor,Initialization,Factory,假设您有某种工厂创建的资源,在构建后仍然属于工厂,如下所示: public class Resource : IDisposable { public void Dispose() { /* ... */ } } public class ResourceManager : IDisposable { public Resource Load() { /* create resource and add to list */ } public void Dispose() { /*

假设您有某种工厂创建的资源,在构建后仍然属于工厂,如下所示:

public class Resource : IDisposable {
  public void Dispose() { /* ... */ }
}

public class ResourceManager : IDisposable {
  public Resource Load() { /* create resource and add to list */ }
  public void Dispose() { /* dispose all loaded resources in list */ }
}
现在您有了一个基类,它需要构造函数中的
资源
实例来初始化:

public class Fooificator {
  public Fooificator(Resource resource) {
    this.resource = resource;
  }
  private Resource resource;
}
从此类基类派生的类如何构造
资源
,而不丢失对工厂的引用

使用静态方法的天真方法无法记住工厂(除了丑陋的黑客行为,比如将其存储在静态字段中,以便构造函数在基类构造完成后提取,或者使用两阶段初始化,其中
资源通过名为
Initialize()
方法的构造函数提供给基类)

一种可能的解决方法是命名构造函数习惯用法:

public class DefaultFooificator : Fooificator, IDisposable {

  public static DefaultFooificator Create() {
    ResourceManager resourceManager = new ResourceManager();
    DefaultFooificator fooificator = new DefaultFooificator(
      resourceManager.Load()
    );
    fooificator.resourceManager = resourceManager;

    return fooificator;
  }

  private DefaultFooificator(Resource resource) : base(resource) {}
  private ResourceManager resourceManager;
}
但是,在解决存储
ResourceManager
引用的问题时,这将不允许从
DefaultFooificator
派生更多的类


有什么优雅的解决方案可以让我进一步从
DefaultFooificator
派生,或者以其他方式存储
ResourceManager
引用吗?

为什么从
Fooificator
派生的类要负责构造
资源?为什么不能将此依赖项注入到它的构造器是什么

public class DefaultFooificator : Fooificator
{
    public DefaultFooificator(Resource resource) : base(resource) {}
}

您可以将资源的创建推迟到<代码> FooPixor工厂> /Cuff>。

< P>我认为您应该考虑您的类是否过于紧密耦合。如果资源具有公共构造函数,每个人都可以创建一个实例并将其作为引用给FooPixor构造函数。这实际上是一件好事。 看起来不那么吸引人的是,您似乎有一个要求,即只有ResourceManager.Load创建的资源才能合法使用(顺便说一句,这违反了命令/查询分离)。但是,API没有强制执行此约束

您应该通过将资源构造函数设置为内部,或者通过解除ResourceManager约束来强制执行此约束

内部构造函数倾向于拉紧类耦合的方向,所以我认真考虑第二个选项。

或者,更改Fooificator的构造函数以引用ResourceManager,或者可能是
Func


如果没有更多的上下文,我想很难给出一个更好的答案。

同意,但如果不让人们解释几页,就很难陈述问题。在实际的代码库中,这是一个XNA游戏,
Resource
ResourceManager
(他们的真名是
Effect
ContentManager
)是由微软的框架提供的,不幸的是,这不在我的控制范围之内类已经使用了一个
internal
构造函数,我只是为了精简代码而省略了它。向
Fooificator
添加
ResourceManager
引用会破坏封装,因为
Resource
实例在实际代码中可以通过
ResourceManager
或通过静态方法创建d
Resource.CompileFromFile()
(也不在我的控制范围内),因此,至少在一种情况下,
ResourceManager
将是
null
@Cygon:感谢您的解释。每当我发现现有API不充分,但我无法更改它时,我通常会创建一个屏蔽我的接口-一个反腐败层,如果您愿意的话。这可能是一个创建Resource inst的接口例如我提到的Func,函数/委托基本上只是匿名的单方法接口…这就是我的最后一个示例所做的。可能你指的是一个抽象工厂,而我的命名构造函数实际上是一个工厂方法,但结果是一样的。这两种情况都不允许派生更多的类从
DefaultFooificator
中,我的原因是运行时不能基于静态方法派生,而您的方法是因为它会将派生类拉入提供
DefaultFooificator
资源的职责中,其中构造它所需的数据是
Defa的私有实现细节咨询者
public class DefaultFooificator : Fooificator
{
    public DefaultFooificator(Resource resource) : base(resource) {}
}