是否有用于初始化通过DI容器创建的对象的模式 [英] Is there a pattern for initializing objects created via a DI container

本文介绍了是否有用于初始化通过DI容器创建的对象的模式的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我试图让Unity来管理我的对象的创建,我想要有一些初始化参数,直到运行时才知道:



在只有这样,我可以想到的方法是在界面上有一个Init方法。

 界面IMyIntf {
void Initialize(string runTimeParam);
string RunTimeParam {get; }
}

然后使用它(在Unity中)我会这样做: p>

  var IMyIntf = unityContainer.Resolve< IMyIntf>(); 
IMyIntf.Initialize(somevalue);

在这种情况下, runTimeParam param由基于用户输入的运行时间。这个简单的例子只是返回值 runTimeParam ,但实际上这个参数会像文件名一样,initialize方法会对文件执行某些操作。



这会产生一些问题,即 Initialize 方法在接口上可用,可以多次调用。在执行中设置一个标志,并且重复调用引发异常。初始化似乎很笨重。



在我解决了我的界面,我不想知道任何关于 IMyIntf 的实现。但是,我想要的是这个接口需要一定时间初始化参数的知识。有没有办法用这种信息来注释(属性?)界面,并在创建对象时将它们传递给框架?



编辑:描述界面有点多

解决方案

任何需要运行时值构建特定依赖关系的地方,抽象工厂是解决方案。



在界面上初始化了一个方法,它们有一个泄漏抽象



在你的情况下,我会说你应该在上使用来模拟 IMyIntf 界面,而不是你打算如何创建其实现。这是一个实现细节。



因此,界面应该是:

  public interface IMyIntf 
{
string RunTimeParam {get;
}

现在定义抽象工厂:

  public interface IMyIntfFactory 
{
IMyIntf Create(string runTimeParam);
}

您现在可以创建一个具体实现 IMyIntfFactory 创建 IMyIntf 的具体实例,如下所示:

  public class MyIntf:IMyIntf 
{
private readonly string runTimeParam;

public MyIntf(string runTimeParam)
{
if(runTimeParam == null)
{
throw new ArgumentNullException(runTimeParam
}

this.runTimeParam = runTimeParam;
}

public string RunTimeParam
{
get {return this.runTimeParam; }
}
}

请注意,这允许我们如何保护通过使用 readonly 关键字的类不变量。没有臭味初始化方法是必需的。



一个 IMyIntfFactory 实现可能很简单:

  public class MyIntfFactory:IMyIntfFactory 
{
public IMyIntf Create(string runTimeParam)
{
返回新的MyIntf(runTimeParam);
}
}

在所有消费者中,您需要一个 IMyIntf 实例,您只需通过构造函数注入请求 IMyIntfFactory >

如果您正确注册了任何DI值,它的盐将能够为您自动连接一个 IMyIntfFactory 实例。 / p>

I am trying to get Unity to manage the creation of my objects and I want to have some initialization parameters that are not known until run-time:

At the moment the only way I could think of the way to do it is to have an Init method on the interface.

interface IMyIntf {
  void Initialize(string runTimeParam);
  string RunTimeParam { get; }
}

Then to use it (in Unity) I would do this:

var IMyIntf = unityContainer.Resolve<IMyIntf>();
IMyIntf.Initialize("somevalue");

In this scenario runTimeParam param is determined at run-time based on user input. The trivial case here simply returns the value of runTimeParam but in reality the parameter will be something like file name and initialize method will do something with the file.

This creates a number of issues, namely that the Initialize method is available on the interface and can be called multiple times. Setting a flag in the implementation and throwing exception on repeated call to Initialize seems way clunky.

At the point where I resolve my interface I don't want to know anything about the implementation of IMyIntf. What I do want, though, is the knowledge that this interface needs certain one time initialization parameters. Is there a way to somehow annotate(attributes?) the interface with this information and pass those to framework when the object is created?

Edit: Described the interface a bit more.

解决方案

Any place where you need a run-time value to construct a particular dependency, Abstract Factory is the solution.

Having Initialize methods on the interfaces smells of a Leaky Abstraction.

In your case I would say that you should model the IMyIntf interface on how you need to use it - not how you intent to create implementations thereof. That's an implementation detail.

Thus, the interface should simply be:

public interface IMyIntf
{
    string RunTimeParam { get; }
}

Now define the Abstract Factory:

public interface IMyIntfFactory
{
    IMyIntf Create(string runTimeParam);
}

You can now create a concrete implementation of IMyIntfFactory that creates concrete instances of IMyIntf like this one:

public class MyIntf : IMyIntf
{
    private readonly string runTimeParam;

    public MyIntf(string runTimeParam)
    {
        if(runTimeParam == null)
        {
            throw new ArgumentNullException("runTimeParam");
        }

        this.runTimeParam = runTimeParam;
    }

    public string RunTimeParam
    {
        get { return this.runTimeParam; }
    }
}

Notice how this allows us to protect the class' invariants by use of the readonly keyword. No smelly Initialize methods are necessary.

An IMyIntfFactory implementation may be as simple as this:

public class MyIntfFactory : IMyIntfFactory
{
    public IMyIntf Create(string runTimeParam)
    {
        return new MyIntf(runTimeParam);
    }
}

In all your consumers where you need an IMyIntf instance, you simply take a dependency on IMyIntfFactory by requesting it through Constructor Injection.

Any DI Container worth its salt will be able to auto-wire an IMyIntfFactory instance for you if you register it correctly.

这篇关于是否有用于初始化通过DI容器创建的对象的模式的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆