无需第三方框架即可实现 DI

发布于 2025-01-05 00:23:08 字数 1438 浏览 1 评论 0原文

我正在编写一个插件作为插件架构的一部分。创建插件的方式是通过反射和CreateInstance。因此调用默认构造函数。这段代码我无法触及,我正在尝试找到一种在无法使用框架的情况下使用 DI 的合理方法。

我相信我有 3 个选择:

i) Poor Man's DI (PMDI)

ii) Factory Pattern

iii) TinyIOC 或类似的(一个处理 DI 的 cs 文件)

我开始查看 PMDI 但随后一个依赖项需要另一个依赖项,所以我最终得到了一些东西与此类似,这很丑陋并且可能变得更糟:

public MyMainPluginClass() : this(new Repo(new Logger()))
{

}

public MyMainPluginClass(IRepo repo)
{

}

然后我转向工厂模式的想法,但找不到任何像样的演示代码。我想我会有这样的东西:

public static FactoryUtility
{
  public static IRepo GetRepo()
  {
    return new Repo(GetLogger());
  }

  public static ILogger GetLogger()
  {
    return new Logger();
  }
}

    public MyMainPluginClass() : this(FactoryUtility.GetRepo())
    {

    }

    public MyMainPluginClass(IRepo repo)
    {

    }

它看起来是这样的吗?

然后我遇到了 TinyIOC 这是一个完成所有依赖项注册的类,但我相信它需要进行设置在我的类库中没有的 Program.cs 中。如果有人有任何使用此功能的经验,可以像这样使用它:

    public MyMainPluginClass()
    {
       var container = TinyIoCContainer.Current;
       container.AutoRegister();
       var implementation = container.Resolve<IRepo>();

       MyMainPluginClass(implementation);
    }

    public MyMainPluginClass(IRepo repo)
    {

    }

是否有任何替代方法可以在不使用第 3 方库的情况下实现 DI,如果没有,会从上面选择哪种方法?

注意:上面的代码尚未编译,只是我认为可行的一个想法。如果它们是有效的方法,请发布更正。

I am writing a plugin as part of a plugin architecture. The way plugins are created is via reflection and CreateInstance. Therefore the default constructor is called. This code I cannot touch and I am trying to find a sensible way to use DI without the ability to use a framework.

I believe I have 3 options:

i) Poor Man's DI (PMDI)

ii) Factory Pattern

iii) TinyIOC or similar (one cs file that handles DI)

I started looking at PMDI but then a dependency needed another dependency so I ended up with something similar to this which is ugly and could get worse:

public MyMainPluginClass() : this(new Repo(new Logger()))
{

}

public MyMainPluginClass(IRepo repo)
{

}

I then moved onto the idea of a Factory Pattern but could not find any decent demo code. I assume I would have something like this:

public static FactoryUtility
{
  public static IRepo GetRepo()
  {
    return new Repo(GetLogger());
  }

  public static ILogger GetLogger()
  {
    return new Logger();
  }
}

    public MyMainPluginClass() : this(FactoryUtility.GetRepo())
    {

    }

    public MyMainPluginClass(IRepo repo)
    {

    }

Is that how it would look?

I then came across TinyIOC which is one class that does all the dependency registering but I believe it requires to be setup in a Program.cs which I don't have in a class library. If someone has any experience using this could it be used like so:

    public MyMainPluginClass()
    {
       var container = TinyIoCContainer.Current;
       container.AutoRegister();
       var implementation = container.Resolve<IRepo>();

       MyMainPluginClass(implementation);
    }

    public MyMainPluginClass(IRepo repo)
    {

    }

Are there any alternative approaches to achieve DI without using a 3rd party library and if not which approach would choose from above?

NOTE: The code above has not been compiled and is just an idea of what I think would work. Please post corrections if they are valid approaches.

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

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

发布评论

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

评论(3

一个人的旅程 2025-01-12 00:23:08

由于您使用的是 .NET 4,因此您可能需要考虑使用 MEF,因为它内置于框架本身中。这看起来相当简单的 DI,MEF 处理得很好,因为它主要用于可扩展性。

有关详细信息,请参阅MEF CodePlex 网站上的“了解更多”页面

Since you're using .NET 4, you might want to consider using MEF, as it's built into the framework itself. This looks like fairly straightforward DI, which MEF handles well, as it's intended mainly for extensibility.

For details, see the Learn More page on the MEF CodePlex site.

黄昏下泛黄的笔记 2025-01-12 00:23:08

我最终选择了TinyIOC。不幸的是,该插件的构造函数在实际启动和运行之前被调用了几次。我只是设置了一个布尔值来防止注册被多次调用,因此它允许我简单地自动注册依赖项,然后我们就可以开始了。

public MyMainPluginClass() : this(FactoryUtility.SetupIOC())
{

}

public MyMainPluginClass(IRepo repo)
{

}

public static class FactoryUtility
{
    private static bool Initialized  = false;

    public static IRepo SetupIOC()
    {
        var container = TinyIoCContainer.Current;

        if (!Initialized)
        {
            container.AutoRegister(new[] { Assembly.GetExecutingAssembly() });

            Initialized = true;
        }

        var result = container.Resolve<IRepo>();

        return result;
    }
}

I went with TinyIOC in the end. Unfortunately the plugin's constructor gets called several times before its actually up and running. I simply set a boolean to prevent registration being called several times and therefore it allows me to simply auto-register dependencies and off we go.

public MyMainPluginClass() : this(FactoryUtility.SetupIOC())
{

}

public MyMainPluginClass(IRepo repo)
{

}

public static class FactoryUtility
{
    private static bool Initialized  = false;

    public static IRepo SetupIOC()
    {
        var container = TinyIoCContainer.Current;

        if (!Initialized)
        {
            container.AutoRegister(new[] { Assembly.GetExecutingAssembly() });

            Initialized = true;
        }

        var result = container.Resolve<IRepo>();

        return result;
    }
}
护你周全 2025-01-12 00:23:08

如果我绝对不想向 DI 容器添加依赖项,我喜欢使用自己的 TinyIOC(对这个名称感到抱歉,不知道它已被采用),对于小型项目,它为我提供了与使用容器,但时钟频率低于 200 LOC。

如果您有兴趣,这里是代码:https://gist.github.com/ad7608e2ae10b0f04229

If I absolutely don't want to add a dependency to a DI container, I like to use my own TinyIOC (sorry about the name, didn't know it was taken), which for small projects gives me the same semantics as using a container, but clocks in at below 200 LOC.

If you are interested, here is the code: https://gist.github.com/ad7608e2ae10b0f04229

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